1e4b17023SJohn Marino /* Common subexpression elimination for GNU compiler.
2e4b17023SJohn Marino Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998
3e4b17023SJohn Marino 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
4e4b17023SJohn Marino 2011 Free Software Foundation, Inc.
5e4b17023SJohn Marino
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11e4b17023SJohn Marino version.
12e4b17023SJohn Marino
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16e4b17023SJohn Marino for more details.
17e4b17023SJohn Marino
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21e4b17023SJohn Marino
22e4b17023SJohn Marino #include "config.h"
23e4b17023SJohn Marino #include "system.h"
24e4b17023SJohn Marino #include "coretypes.h"
25e4b17023SJohn Marino #include "tm.h"
26e4b17023SJohn Marino #include "rtl.h"
27e4b17023SJohn Marino #include "tm_p.h"
28e4b17023SJohn Marino #include "hard-reg-set.h"
29e4b17023SJohn Marino #include "regs.h"
30e4b17023SJohn Marino #include "basic-block.h"
31e4b17023SJohn Marino #include "flags.h"
32e4b17023SJohn Marino #include "insn-config.h"
33e4b17023SJohn Marino #include "recog.h"
34e4b17023SJohn Marino #include "function.h"
35e4b17023SJohn Marino #include "expr.h"
36e4b17023SJohn Marino #include "diagnostic-core.h"
37e4b17023SJohn Marino #include "toplev.h"
38e4b17023SJohn Marino #include "output.h"
39e4b17023SJohn Marino #include "ggc.h"
40e4b17023SJohn Marino #include "timevar.h"
41e4b17023SJohn Marino #include "except.h"
42e4b17023SJohn Marino #include "target.h"
43e4b17023SJohn Marino #include "params.h"
44e4b17023SJohn Marino #include "rtlhooks-def.h"
45e4b17023SJohn Marino #include "tree-pass.h"
46e4b17023SJohn Marino #include "df.h"
47e4b17023SJohn Marino #include "dbgcnt.h"
48e4b17023SJohn Marino
49e4b17023SJohn Marino /* The basic idea of common subexpression elimination is to go
50e4b17023SJohn Marino through the code, keeping a record of expressions that would
51e4b17023SJohn Marino have the same value at the current scan point, and replacing
52e4b17023SJohn Marino expressions encountered with the cheapest equivalent expression.
53e4b17023SJohn Marino
54e4b17023SJohn Marino It is too complicated to keep track of the different possibilities
55e4b17023SJohn Marino when control paths merge in this code; so, at each label, we forget all
56e4b17023SJohn Marino that is known and start fresh. This can be described as processing each
57e4b17023SJohn Marino extended basic block separately. We have a separate pass to perform
58e4b17023SJohn Marino global CSE.
59e4b17023SJohn Marino
60e4b17023SJohn Marino Note CSE can turn a conditional or computed jump into a nop or
61e4b17023SJohn Marino an unconditional jump. When this occurs we arrange to run the jump
62e4b17023SJohn Marino optimizer after CSE to delete the unreachable code.
63e4b17023SJohn Marino
64e4b17023SJohn Marino We use two data structures to record the equivalent expressions:
65e4b17023SJohn Marino a hash table for most expressions, and a vector of "quantity
66e4b17023SJohn Marino numbers" to record equivalent (pseudo) registers.
67e4b17023SJohn Marino
68e4b17023SJohn Marino The use of the special data structure for registers is desirable
69e4b17023SJohn Marino because it is faster. It is possible because registers references
70e4b17023SJohn Marino contain a fairly small number, the register number, taken from
71e4b17023SJohn Marino a contiguously allocated series, and two register references are
72e4b17023SJohn Marino identical if they have the same number. General expressions
73e4b17023SJohn Marino do not have any such thing, so the only way to retrieve the
74e4b17023SJohn Marino information recorded on an expression other than a register
75e4b17023SJohn Marino is to keep it in a hash table.
76e4b17023SJohn Marino
77e4b17023SJohn Marino Registers and "quantity numbers":
78e4b17023SJohn Marino
79e4b17023SJohn Marino At the start of each basic block, all of the (hardware and pseudo)
80e4b17023SJohn Marino registers used in the function are given distinct quantity
81e4b17023SJohn Marino numbers to indicate their contents. During scan, when the code
82e4b17023SJohn Marino copies one register into another, we copy the quantity number.
83e4b17023SJohn Marino When a register is loaded in any other way, we allocate a new
84e4b17023SJohn Marino quantity number to describe the value generated by this operation.
85e4b17023SJohn Marino `REG_QTY (N)' records what quantity register N is currently thought
86e4b17023SJohn Marino of as containing.
87e4b17023SJohn Marino
88e4b17023SJohn Marino All real quantity numbers are greater than or equal to zero.
89e4b17023SJohn Marino If register N has not been assigned a quantity, `REG_QTY (N)' will
90e4b17023SJohn Marino equal -N - 1, which is always negative.
91e4b17023SJohn Marino
92e4b17023SJohn Marino Quantity numbers below zero do not exist and none of the `qty_table'
93e4b17023SJohn Marino entries should be referenced with a negative index.
94e4b17023SJohn Marino
95e4b17023SJohn Marino We also maintain a bidirectional chain of registers for each
96e4b17023SJohn Marino quantity number. The `qty_table` members `first_reg' and `last_reg',
97e4b17023SJohn Marino and `reg_eqv_table' members `next' and `prev' hold these chains.
98e4b17023SJohn Marino
99e4b17023SJohn Marino The first register in a chain is the one whose lifespan is least local.
100e4b17023SJohn Marino Among equals, it is the one that was seen first.
101e4b17023SJohn Marino We replace any equivalent register with that one.
102e4b17023SJohn Marino
103e4b17023SJohn Marino If two registers have the same quantity number, it must be true that
104e4b17023SJohn Marino REG expressions with qty_table `mode' must be in the hash table for both
105e4b17023SJohn Marino registers and must be in the same class.
106e4b17023SJohn Marino
107e4b17023SJohn Marino The converse is not true. Since hard registers may be referenced in
108e4b17023SJohn Marino any mode, two REG expressions might be equivalent in the hash table
109e4b17023SJohn Marino but not have the same quantity number if the quantity number of one
110e4b17023SJohn Marino of the registers is not the same mode as those expressions.
111e4b17023SJohn Marino
112e4b17023SJohn Marino Constants and quantity numbers
113e4b17023SJohn Marino
114e4b17023SJohn Marino When a quantity has a known constant value, that value is stored
115e4b17023SJohn Marino in the appropriate qty_table `const_rtx'. This is in addition to
116e4b17023SJohn Marino putting the constant in the hash table as is usual for non-regs.
117e4b17023SJohn Marino
118e4b17023SJohn Marino Whether a reg or a constant is preferred is determined by the configuration
119e4b17023SJohn Marino macro CONST_COSTS and will often depend on the constant value. In any
120e4b17023SJohn Marino event, expressions containing constants can be simplified, by fold_rtx.
121e4b17023SJohn Marino
122e4b17023SJohn Marino When a quantity has a known nearly constant value (such as an address
123e4b17023SJohn Marino of a stack slot), that value is stored in the appropriate qty_table
124e4b17023SJohn Marino `const_rtx'.
125e4b17023SJohn Marino
126e4b17023SJohn Marino Integer constants don't have a machine mode. However, cse
127e4b17023SJohn Marino determines the intended machine mode from the destination
128e4b17023SJohn Marino of the instruction that moves the constant. The machine mode
129e4b17023SJohn Marino is recorded in the hash table along with the actual RTL
130e4b17023SJohn Marino constant expression so that different modes are kept separate.
131e4b17023SJohn Marino
132e4b17023SJohn Marino Other expressions:
133e4b17023SJohn Marino
134e4b17023SJohn Marino To record known equivalences among expressions in general
135e4b17023SJohn Marino we use a hash table called `table'. It has a fixed number of buckets
136e4b17023SJohn Marino that contain chains of `struct table_elt' elements for expressions.
137e4b17023SJohn Marino These chains connect the elements whose expressions have the same
138e4b17023SJohn Marino hash codes.
139e4b17023SJohn Marino
140e4b17023SJohn Marino Other chains through the same elements connect the elements which
141e4b17023SJohn Marino currently have equivalent values.
142e4b17023SJohn Marino
143e4b17023SJohn Marino Register references in an expression are canonicalized before hashing
144e4b17023SJohn Marino the expression. This is done using `reg_qty' and qty_table `first_reg'.
145e4b17023SJohn Marino The hash code of a register reference is computed using the quantity
146e4b17023SJohn Marino number, not the register number.
147e4b17023SJohn Marino
148e4b17023SJohn Marino When the value of an expression changes, it is necessary to remove from the
149e4b17023SJohn Marino hash table not just that expression but all expressions whose values
150e4b17023SJohn Marino could be different as a result.
151e4b17023SJohn Marino
152e4b17023SJohn Marino 1. If the value changing is in memory, except in special cases
153e4b17023SJohn Marino ANYTHING referring to memory could be changed. That is because
154e4b17023SJohn Marino nobody knows where a pointer does not point.
155e4b17023SJohn Marino The function `invalidate_memory' removes what is necessary.
156e4b17023SJohn Marino
157e4b17023SJohn Marino The special cases are when the address is constant or is
158e4b17023SJohn Marino a constant plus a fixed register such as the frame pointer
159e4b17023SJohn Marino or a static chain pointer. When such addresses are stored in,
160e4b17023SJohn Marino we can tell exactly which other such addresses must be invalidated
161e4b17023SJohn Marino due to overlap. `invalidate' does this.
162e4b17023SJohn Marino All expressions that refer to non-constant
163e4b17023SJohn Marino memory addresses are also invalidated. `invalidate_memory' does this.
164e4b17023SJohn Marino
165e4b17023SJohn Marino 2. If the value changing is a register, all expressions
166e4b17023SJohn Marino containing references to that register, and only those,
167e4b17023SJohn Marino must be removed.
168e4b17023SJohn Marino
169e4b17023SJohn Marino Because searching the entire hash table for expressions that contain
170e4b17023SJohn Marino a register is very slow, we try to figure out when it isn't necessary.
171e4b17023SJohn Marino Precisely, this is necessary only when expressions have been
172e4b17023SJohn Marino entered in the hash table using this register, and then the value has
173e4b17023SJohn Marino changed, and then another expression wants to be added to refer to
174e4b17023SJohn Marino the register's new value. This sequence of circumstances is rare
175e4b17023SJohn Marino within any one basic block.
176e4b17023SJohn Marino
177e4b17023SJohn Marino `REG_TICK' and `REG_IN_TABLE', accessors for members of
178e4b17023SJohn Marino cse_reg_info, are used to detect this case. REG_TICK (i) is
179e4b17023SJohn Marino incremented whenever a value is stored in register i.
180e4b17023SJohn Marino REG_IN_TABLE (i) holds -1 if no references to register i have been
181e4b17023SJohn Marino entered in the table; otherwise, it contains the value REG_TICK (i)
182e4b17023SJohn Marino had when the references were entered. If we want to enter a
183e4b17023SJohn Marino reference and REG_IN_TABLE (i) != REG_TICK (i), we must scan and
184e4b17023SJohn Marino remove old references. Until we want to enter a new entry, the
185e4b17023SJohn Marino mere fact that the two vectors don't match makes the entries be
186e4b17023SJohn Marino ignored if anyone tries to match them.
187e4b17023SJohn Marino
188e4b17023SJohn Marino Registers themselves are entered in the hash table as well as in
189e4b17023SJohn Marino the equivalent-register chains. However, `REG_TICK' and
190e4b17023SJohn Marino `REG_IN_TABLE' do not apply to expressions which are simple
191e4b17023SJohn Marino register references. These expressions are removed from the table
192e4b17023SJohn Marino immediately when they become invalid, and this can be done even if
193e4b17023SJohn Marino we do not immediately search for all the expressions that refer to
194e4b17023SJohn Marino the register.
195e4b17023SJohn Marino
196e4b17023SJohn Marino A CLOBBER rtx in an instruction invalidates its operand for further
197e4b17023SJohn Marino reuse. A CLOBBER or SET rtx whose operand is a MEM:BLK
198e4b17023SJohn Marino invalidates everything that resides in memory.
199e4b17023SJohn Marino
200e4b17023SJohn Marino Related expressions:
201e4b17023SJohn Marino
202e4b17023SJohn Marino Constant expressions that differ only by an additive integer
203e4b17023SJohn Marino are called related. When a constant expression is put in
204e4b17023SJohn Marino the table, the related expression with no constant term
205e4b17023SJohn Marino is also entered. These are made to point at each other
206e4b17023SJohn Marino so that it is possible to find out if there exists any
207e4b17023SJohn Marino register equivalent to an expression related to a given expression. */
208e4b17023SJohn Marino
209e4b17023SJohn Marino /* Length of qty_table vector. We know in advance we will not need
210e4b17023SJohn Marino a quantity number this big. */
211e4b17023SJohn Marino
212e4b17023SJohn Marino static int max_qty;
213e4b17023SJohn Marino
214e4b17023SJohn Marino /* Next quantity number to be allocated.
215e4b17023SJohn Marino This is 1 + the largest number needed so far. */
216e4b17023SJohn Marino
217e4b17023SJohn Marino static int next_qty;
218e4b17023SJohn Marino
219e4b17023SJohn Marino /* Per-qty information tracking.
220e4b17023SJohn Marino
221e4b17023SJohn Marino `first_reg' and `last_reg' track the head and tail of the
222e4b17023SJohn Marino chain of registers which currently contain this quantity.
223e4b17023SJohn Marino
224e4b17023SJohn Marino `mode' contains the machine mode of this quantity.
225e4b17023SJohn Marino
226e4b17023SJohn Marino `const_rtx' holds the rtx of the constant value of this
227e4b17023SJohn Marino quantity, if known. A summations of the frame/arg pointer
228e4b17023SJohn Marino and a constant can also be entered here. When this holds
229e4b17023SJohn Marino a known value, `const_insn' is the insn which stored the
230e4b17023SJohn Marino constant value.
231e4b17023SJohn Marino
232e4b17023SJohn Marino `comparison_{code,const,qty}' are used to track when a
233e4b17023SJohn Marino comparison between a quantity and some constant or register has
234e4b17023SJohn Marino been passed. In such a case, we know the results of the comparison
235e4b17023SJohn Marino in case we see it again. These members record a comparison that
236e4b17023SJohn Marino is known to be true. `comparison_code' holds the rtx code of such
237e4b17023SJohn Marino a comparison, else it is set to UNKNOWN and the other two
238e4b17023SJohn Marino comparison members are undefined. `comparison_const' holds
239e4b17023SJohn Marino the constant being compared against, or zero if the comparison
240e4b17023SJohn Marino is not against a constant. `comparison_qty' holds the quantity
241e4b17023SJohn Marino being compared against when the result is known. If the comparison
242e4b17023SJohn Marino is not with a register, `comparison_qty' is -1. */
243e4b17023SJohn Marino
244e4b17023SJohn Marino struct qty_table_elem
245e4b17023SJohn Marino {
246e4b17023SJohn Marino rtx const_rtx;
247e4b17023SJohn Marino rtx const_insn;
248e4b17023SJohn Marino rtx comparison_const;
249e4b17023SJohn Marino int comparison_qty;
250e4b17023SJohn Marino unsigned int first_reg, last_reg;
251e4b17023SJohn Marino /* The sizes of these fields should match the sizes of the
252e4b17023SJohn Marino code and mode fields of struct rtx_def (see rtl.h). */
253e4b17023SJohn Marino ENUM_BITFIELD(rtx_code) comparison_code : 16;
254e4b17023SJohn Marino ENUM_BITFIELD(machine_mode) mode : 8;
255e4b17023SJohn Marino };
256e4b17023SJohn Marino
257e4b17023SJohn Marino /* The table of all qtys, indexed by qty number. */
258e4b17023SJohn Marino static struct qty_table_elem *qty_table;
259e4b17023SJohn Marino
260e4b17023SJohn Marino /* Structure used to pass arguments via for_each_rtx to function
261e4b17023SJohn Marino cse_change_cc_mode. */
262e4b17023SJohn Marino struct change_cc_mode_args
263e4b17023SJohn Marino {
264e4b17023SJohn Marino rtx insn;
265e4b17023SJohn Marino rtx newreg;
266e4b17023SJohn Marino };
267e4b17023SJohn Marino
268e4b17023SJohn Marino #ifdef HAVE_cc0
269e4b17023SJohn Marino /* For machines that have a CC0, we do not record its value in the hash
270e4b17023SJohn Marino table since its use is guaranteed to be the insn immediately following
271e4b17023SJohn Marino its definition and any other insn is presumed to invalidate it.
272e4b17023SJohn Marino
273e4b17023SJohn Marino Instead, we store below the current and last value assigned to CC0.
274e4b17023SJohn Marino If it should happen to be a constant, it is stored in preference
275e4b17023SJohn Marino to the actual assigned value. In case it is a constant, we store
276e4b17023SJohn Marino the mode in which the constant should be interpreted. */
277e4b17023SJohn Marino
278e4b17023SJohn Marino static rtx this_insn_cc0, prev_insn_cc0;
279e4b17023SJohn Marino static enum machine_mode this_insn_cc0_mode, prev_insn_cc0_mode;
280e4b17023SJohn Marino #endif
281e4b17023SJohn Marino
282e4b17023SJohn Marino /* Insn being scanned. */
283e4b17023SJohn Marino
284e4b17023SJohn Marino static rtx this_insn;
285e4b17023SJohn Marino static bool optimize_this_for_speed_p;
286e4b17023SJohn Marino
287e4b17023SJohn Marino /* Index by register number, gives the number of the next (or
288e4b17023SJohn Marino previous) register in the chain of registers sharing the same
289e4b17023SJohn Marino value.
290e4b17023SJohn Marino
291e4b17023SJohn Marino Or -1 if this register is at the end of the chain.
292e4b17023SJohn Marino
293e4b17023SJohn Marino If REG_QTY (N) == -N - 1, reg_eqv_table[N].next is undefined. */
294e4b17023SJohn Marino
295e4b17023SJohn Marino /* Per-register equivalence chain. */
296e4b17023SJohn Marino struct reg_eqv_elem
297e4b17023SJohn Marino {
298e4b17023SJohn Marino int next, prev;
299e4b17023SJohn Marino };
300e4b17023SJohn Marino
301e4b17023SJohn Marino /* The table of all register equivalence chains. */
302e4b17023SJohn Marino static struct reg_eqv_elem *reg_eqv_table;
303e4b17023SJohn Marino
304e4b17023SJohn Marino struct cse_reg_info
305e4b17023SJohn Marino {
306e4b17023SJohn Marino /* The timestamp at which this register is initialized. */
307e4b17023SJohn Marino unsigned int timestamp;
308e4b17023SJohn Marino
309e4b17023SJohn Marino /* The quantity number of the register's current contents. */
310e4b17023SJohn Marino int reg_qty;
311e4b17023SJohn Marino
312e4b17023SJohn Marino /* The number of times the register has been altered in the current
313e4b17023SJohn Marino basic block. */
314e4b17023SJohn Marino int reg_tick;
315e4b17023SJohn Marino
316e4b17023SJohn Marino /* The REG_TICK value at which rtx's containing this register are
317e4b17023SJohn Marino valid in the hash table. If this does not equal the current
318e4b17023SJohn Marino reg_tick value, such expressions existing in the hash table are
319e4b17023SJohn Marino invalid. */
320e4b17023SJohn Marino int reg_in_table;
321e4b17023SJohn Marino
322e4b17023SJohn Marino /* The SUBREG that was set when REG_TICK was last incremented. Set
323e4b17023SJohn Marino to -1 if the last store was to the whole register, not a subreg. */
324e4b17023SJohn Marino unsigned int subreg_ticked;
325e4b17023SJohn Marino };
326e4b17023SJohn Marino
327e4b17023SJohn Marino /* A table of cse_reg_info indexed by register numbers. */
328e4b17023SJohn Marino static struct cse_reg_info *cse_reg_info_table;
329e4b17023SJohn Marino
330e4b17023SJohn Marino /* The size of the above table. */
331e4b17023SJohn Marino static unsigned int cse_reg_info_table_size;
332e4b17023SJohn Marino
333e4b17023SJohn Marino /* The index of the first entry that has not been initialized. */
334e4b17023SJohn Marino static unsigned int cse_reg_info_table_first_uninitialized;
335e4b17023SJohn Marino
336e4b17023SJohn Marino /* The timestamp at the beginning of the current run of
337e4b17023SJohn Marino cse_extended_basic_block. We increment this variable at the beginning of
338e4b17023SJohn Marino the current run of cse_extended_basic_block. The timestamp field of a
339e4b17023SJohn Marino cse_reg_info entry matches the value of this variable if and only
340e4b17023SJohn Marino if the entry has been initialized during the current run of
341e4b17023SJohn Marino cse_extended_basic_block. */
342e4b17023SJohn Marino static unsigned int cse_reg_info_timestamp;
343e4b17023SJohn Marino
344e4b17023SJohn Marino /* A HARD_REG_SET containing all the hard registers for which there is
345e4b17023SJohn Marino currently a REG expression in the hash table. Note the difference
346e4b17023SJohn Marino from the above variables, which indicate if the REG is mentioned in some
347e4b17023SJohn Marino expression in the table. */
348e4b17023SJohn Marino
349e4b17023SJohn Marino static HARD_REG_SET hard_regs_in_table;
350e4b17023SJohn Marino
351e4b17023SJohn Marino /* True if CSE has altered the CFG. */
352e4b17023SJohn Marino static bool cse_cfg_altered;
353e4b17023SJohn Marino
354e4b17023SJohn Marino /* True if CSE has altered conditional jump insns in such a way
355e4b17023SJohn Marino that jump optimization should be redone. */
356e4b17023SJohn Marino static bool cse_jumps_altered;
357e4b17023SJohn Marino
358e4b17023SJohn Marino /* True if we put a LABEL_REF into the hash table for an INSN
359e4b17023SJohn Marino without a REG_LABEL_OPERAND, we have to rerun jump after CSE
360e4b17023SJohn Marino to put in the note. */
361e4b17023SJohn Marino static bool recorded_label_ref;
362e4b17023SJohn Marino
363e4b17023SJohn Marino /* canon_hash stores 1 in do_not_record
364e4b17023SJohn Marino if it notices a reference to CC0, PC, or some other volatile
365e4b17023SJohn Marino subexpression. */
366e4b17023SJohn Marino
367e4b17023SJohn Marino static int do_not_record;
368e4b17023SJohn Marino
369e4b17023SJohn Marino /* canon_hash stores 1 in hash_arg_in_memory
370e4b17023SJohn Marino if it notices a reference to memory within the expression being hashed. */
371e4b17023SJohn Marino
372e4b17023SJohn Marino static int hash_arg_in_memory;
373e4b17023SJohn Marino
374e4b17023SJohn Marino /* The hash table contains buckets which are chains of `struct table_elt's,
375e4b17023SJohn Marino each recording one expression's information.
376e4b17023SJohn Marino That expression is in the `exp' field.
377e4b17023SJohn Marino
378e4b17023SJohn Marino The canon_exp field contains a canonical (from the point of view of
379e4b17023SJohn Marino alias analysis) version of the `exp' field.
380e4b17023SJohn Marino
381e4b17023SJohn Marino Those elements with the same hash code are chained in both directions
382e4b17023SJohn Marino through the `next_same_hash' and `prev_same_hash' fields.
383e4b17023SJohn Marino
384e4b17023SJohn Marino Each set of expressions with equivalent values
385e4b17023SJohn Marino are on a two-way chain through the `next_same_value'
386e4b17023SJohn Marino and `prev_same_value' fields, and all point with
387e4b17023SJohn Marino the `first_same_value' field at the first element in
388e4b17023SJohn Marino that chain. The chain is in order of increasing cost.
389e4b17023SJohn Marino Each element's cost value is in its `cost' field.
390e4b17023SJohn Marino
391e4b17023SJohn Marino The `in_memory' field is nonzero for elements that
392e4b17023SJohn Marino involve any reference to memory. These elements are removed
393e4b17023SJohn Marino whenever a write is done to an unidentified location in memory.
394e4b17023SJohn Marino To be safe, we assume that a memory address is unidentified unless
395e4b17023SJohn Marino the address is either a symbol constant or a constant plus
396e4b17023SJohn Marino the frame pointer or argument pointer.
397e4b17023SJohn Marino
398e4b17023SJohn Marino The `related_value' field is used to connect related expressions
399e4b17023SJohn Marino (that differ by adding an integer).
400e4b17023SJohn Marino The related expressions are chained in a circular fashion.
401e4b17023SJohn Marino `related_value' is zero for expressions for which this
402e4b17023SJohn Marino chain is not useful.
403e4b17023SJohn Marino
404e4b17023SJohn Marino The `cost' field stores the cost of this element's expression.
405e4b17023SJohn Marino The `regcost' field stores the value returned by approx_reg_cost for
406e4b17023SJohn Marino this element's expression.
407e4b17023SJohn Marino
408e4b17023SJohn Marino The `is_const' flag is set if the element is a constant (including
409e4b17023SJohn Marino a fixed address).
410e4b17023SJohn Marino
411e4b17023SJohn Marino The `flag' field is used as a temporary during some search routines.
412e4b17023SJohn Marino
413e4b17023SJohn Marino The `mode' field is usually the same as GET_MODE (`exp'), but
414e4b17023SJohn Marino if `exp' is a CONST_INT and has no machine mode then the `mode'
415e4b17023SJohn Marino field is the mode it was being used as. Each constant is
416e4b17023SJohn Marino recorded separately for each mode it is used with. */
417e4b17023SJohn Marino
418e4b17023SJohn Marino struct table_elt
419e4b17023SJohn Marino {
420e4b17023SJohn Marino rtx exp;
421e4b17023SJohn Marino rtx canon_exp;
422e4b17023SJohn Marino struct table_elt *next_same_hash;
423e4b17023SJohn Marino struct table_elt *prev_same_hash;
424e4b17023SJohn Marino struct table_elt *next_same_value;
425e4b17023SJohn Marino struct table_elt *prev_same_value;
426e4b17023SJohn Marino struct table_elt *first_same_value;
427e4b17023SJohn Marino struct table_elt *related_value;
428e4b17023SJohn Marino int cost;
429e4b17023SJohn Marino int regcost;
430e4b17023SJohn Marino /* The size of this field should match the size
431e4b17023SJohn Marino of the mode field of struct rtx_def (see rtl.h). */
432e4b17023SJohn Marino ENUM_BITFIELD(machine_mode) mode : 8;
433e4b17023SJohn Marino char in_memory;
434e4b17023SJohn Marino char is_const;
435e4b17023SJohn Marino char flag;
436e4b17023SJohn Marino };
437e4b17023SJohn Marino
438e4b17023SJohn Marino /* We don't want a lot of buckets, because we rarely have very many
439e4b17023SJohn Marino things stored in the hash table, and a lot of buckets slows
440e4b17023SJohn Marino down a lot of loops that happen frequently. */
441e4b17023SJohn Marino #define HASH_SHIFT 5
442e4b17023SJohn Marino #define HASH_SIZE (1 << HASH_SHIFT)
443e4b17023SJohn Marino #define HASH_MASK (HASH_SIZE - 1)
444e4b17023SJohn Marino
445e4b17023SJohn Marino /* Compute hash code of X in mode M. Special-case case where X is a pseudo
446e4b17023SJohn Marino register (hard registers may require `do_not_record' to be set). */
447e4b17023SJohn Marino
448e4b17023SJohn Marino #define HASH(X, M) \
449e4b17023SJohn Marino ((REG_P (X) && REGNO (X) >= FIRST_PSEUDO_REGISTER \
450e4b17023SJohn Marino ? (((unsigned) REG << 7) + (unsigned) REG_QTY (REGNO (X))) \
451e4b17023SJohn Marino : canon_hash (X, M)) & HASH_MASK)
452e4b17023SJohn Marino
453e4b17023SJohn Marino /* Like HASH, but without side-effects. */
454e4b17023SJohn Marino #define SAFE_HASH(X, M) \
455e4b17023SJohn Marino ((REG_P (X) && REGNO (X) >= FIRST_PSEUDO_REGISTER \
456e4b17023SJohn Marino ? (((unsigned) REG << 7) + (unsigned) REG_QTY (REGNO (X))) \
457e4b17023SJohn Marino : safe_hash (X, M)) & HASH_MASK)
458e4b17023SJohn Marino
459e4b17023SJohn Marino /* Determine whether register number N is considered a fixed register for the
460e4b17023SJohn Marino purpose of approximating register costs.
461e4b17023SJohn Marino It is desirable to replace other regs with fixed regs, to reduce need for
462e4b17023SJohn Marino non-fixed hard regs.
463e4b17023SJohn Marino A reg wins if it is either the frame pointer or designated as fixed. */
464e4b17023SJohn Marino #define FIXED_REGNO_P(N) \
465e4b17023SJohn Marino ((N) == FRAME_POINTER_REGNUM || (N) == HARD_FRAME_POINTER_REGNUM \
466e4b17023SJohn Marino || fixed_regs[N] || global_regs[N])
467e4b17023SJohn Marino
468e4b17023SJohn Marino /* Compute cost of X, as stored in the `cost' field of a table_elt. Fixed
469e4b17023SJohn Marino hard registers and pointers into the frame are the cheapest with a cost
470e4b17023SJohn Marino of 0. Next come pseudos with a cost of one and other hard registers with
471e4b17023SJohn Marino a cost of 2. Aside from these special cases, call `rtx_cost'. */
472e4b17023SJohn Marino
473e4b17023SJohn Marino #define CHEAP_REGNO(N) \
474e4b17023SJohn Marino (REGNO_PTR_FRAME_P(N) \
475e4b17023SJohn Marino || (HARD_REGISTER_NUM_P (N) \
476e4b17023SJohn Marino && FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
477e4b17023SJohn Marino
478e4b17023SJohn Marino #define COST(X) (REG_P (X) ? 0 : notreg_cost (X, SET, 1))
479e4b17023SJohn Marino #define COST_IN(X, OUTER, OPNO) (REG_P (X) ? 0 : notreg_cost (X, OUTER, OPNO))
480e4b17023SJohn Marino
481e4b17023SJohn Marino /* Get the number of times this register has been updated in this
482e4b17023SJohn Marino basic block. */
483e4b17023SJohn Marino
484e4b17023SJohn Marino #define REG_TICK(N) (get_cse_reg_info (N)->reg_tick)
485e4b17023SJohn Marino
486e4b17023SJohn Marino /* Get the point at which REG was recorded in the table. */
487e4b17023SJohn Marino
488e4b17023SJohn Marino #define REG_IN_TABLE(N) (get_cse_reg_info (N)->reg_in_table)
489e4b17023SJohn Marino
490e4b17023SJohn Marino /* Get the SUBREG set at the last increment to REG_TICK (-1 if not a
491e4b17023SJohn Marino SUBREG). */
492e4b17023SJohn Marino
493e4b17023SJohn Marino #define SUBREG_TICKED(N) (get_cse_reg_info (N)->subreg_ticked)
494e4b17023SJohn Marino
495e4b17023SJohn Marino /* Get the quantity number for REG. */
496e4b17023SJohn Marino
497e4b17023SJohn Marino #define REG_QTY(N) (get_cse_reg_info (N)->reg_qty)
498e4b17023SJohn Marino
499e4b17023SJohn Marino /* Determine if the quantity number for register X represents a valid index
500e4b17023SJohn Marino into the qty_table. */
501e4b17023SJohn Marino
502e4b17023SJohn Marino #define REGNO_QTY_VALID_P(N) (REG_QTY (N) >= 0)
503e4b17023SJohn Marino
504e4b17023SJohn Marino /* Compare table_elt X and Y and return true iff X is cheaper than Y. */
505e4b17023SJohn Marino
506e4b17023SJohn Marino #define CHEAPER(X, Y) \
507e4b17023SJohn Marino (preferable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
508e4b17023SJohn Marino
509e4b17023SJohn Marino static struct table_elt *table[HASH_SIZE];
510e4b17023SJohn Marino
511e4b17023SJohn Marino /* Chain of `struct table_elt's made so far for this function
512e4b17023SJohn Marino but currently removed from the table. */
513e4b17023SJohn Marino
514e4b17023SJohn Marino static struct table_elt *free_element_chain;
515e4b17023SJohn Marino
516e4b17023SJohn Marino /* Set to the cost of a constant pool reference if one was found for a
517e4b17023SJohn Marino symbolic constant. If this was found, it means we should try to
518e4b17023SJohn Marino convert constants into constant pool entries if they don't fit in
519e4b17023SJohn Marino the insn. */
520e4b17023SJohn Marino
521e4b17023SJohn Marino static int constant_pool_entries_cost;
522e4b17023SJohn Marino static int constant_pool_entries_regcost;
523e4b17023SJohn Marino
524e4b17023SJohn Marino /* Trace a patch through the CFG. */
525e4b17023SJohn Marino
526e4b17023SJohn Marino struct branch_path
527e4b17023SJohn Marino {
528e4b17023SJohn Marino /* The basic block for this path entry. */
529e4b17023SJohn Marino basic_block bb;
530e4b17023SJohn Marino };
531e4b17023SJohn Marino
532e4b17023SJohn Marino /* This data describes a block that will be processed by
533e4b17023SJohn Marino cse_extended_basic_block. */
534e4b17023SJohn Marino
535e4b17023SJohn Marino struct cse_basic_block_data
536e4b17023SJohn Marino {
537e4b17023SJohn Marino /* Total number of SETs in block. */
538e4b17023SJohn Marino int nsets;
539e4b17023SJohn Marino /* Size of current branch path, if any. */
540e4b17023SJohn Marino int path_size;
541e4b17023SJohn Marino /* Current path, indicating which basic_blocks will be processed. */
542e4b17023SJohn Marino struct branch_path *path;
543e4b17023SJohn Marino };
544e4b17023SJohn Marino
545e4b17023SJohn Marino
546e4b17023SJohn Marino /* Pointers to the live in/live out bitmaps for the boundaries of the
547e4b17023SJohn Marino current EBB. */
548e4b17023SJohn Marino static bitmap cse_ebb_live_in, cse_ebb_live_out;
549e4b17023SJohn Marino
550e4b17023SJohn Marino /* A simple bitmap to track which basic blocks have been visited
551e4b17023SJohn Marino already as part of an already processed extended basic block. */
552e4b17023SJohn Marino static sbitmap cse_visited_basic_blocks;
553e4b17023SJohn Marino
554e4b17023SJohn Marino static bool fixed_base_plus_p (rtx x);
555e4b17023SJohn Marino static int notreg_cost (rtx, enum rtx_code, int);
556e4b17023SJohn Marino static int approx_reg_cost_1 (rtx *, void *);
557e4b17023SJohn Marino static int approx_reg_cost (rtx);
558e4b17023SJohn Marino static int preferable (int, int, int, int);
559e4b17023SJohn Marino static void new_basic_block (void);
560e4b17023SJohn Marino static void make_new_qty (unsigned int, enum machine_mode);
561e4b17023SJohn Marino static void make_regs_eqv (unsigned int, unsigned int);
562e4b17023SJohn Marino static void delete_reg_equiv (unsigned int);
563e4b17023SJohn Marino static int mention_regs (rtx);
564e4b17023SJohn Marino static int insert_regs (rtx, struct table_elt *, int);
565e4b17023SJohn Marino static void remove_from_table (struct table_elt *, unsigned);
566e4b17023SJohn Marino static void remove_pseudo_from_table (rtx, unsigned);
567e4b17023SJohn Marino static struct table_elt *lookup (rtx, unsigned, enum machine_mode);
568e4b17023SJohn Marino static struct table_elt *lookup_for_remove (rtx, unsigned, enum machine_mode);
569e4b17023SJohn Marino static rtx lookup_as_function (rtx, enum rtx_code);
570e4b17023SJohn Marino static struct table_elt *insert_with_costs (rtx, struct table_elt *, unsigned,
571e4b17023SJohn Marino enum machine_mode, int, int);
572e4b17023SJohn Marino static struct table_elt *insert (rtx, struct table_elt *, unsigned,
573e4b17023SJohn Marino enum machine_mode);
574e4b17023SJohn Marino static void merge_equiv_classes (struct table_elt *, struct table_elt *);
575e4b17023SJohn Marino static void invalidate (rtx, enum machine_mode);
576e4b17023SJohn Marino static void remove_invalid_refs (unsigned int);
577e4b17023SJohn Marino static void remove_invalid_subreg_refs (unsigned int, unsigned int,
578e4b17023SJohn Marino enum machine_mode);
579e4b17023SJohn Marino static void rehash_using_reg (rtx);
580e4b17023SJohn Marino static void invalidate_memory (void);
581e4b17023SJohn Marino static void invalidate_for_call (void);
582e4b17023SJohn Marino static rtx use_related_value (rtx, struct table_elt *);
583e4b17023SJohn Marino
584e4b17023SJohn Marino static inline unsigned canon_hash (rtx, enum machine_mode);
585e4b17023SJohn Marino static inline unsigned safe_hash (rtx, enum machine_mode);
586e4b17023SJohn Marino static inline unsigned hash_rtx_string (const char *);
587e4b17023SJohn Marino
588e4b17023SJohn Marino static rtx canon_reg (rtx, rtx);
589e4b17023SJohn Marino static enum rtx_code find_comparison_args (enum rtx_code, rtx *, rtx *,
590e4b17023SJohn Marino enum machine_mode *,
591e4b17023SJohn Marino enum machine_mode *);
592e4b17023SJohn Marino static rtx fold_rtx (rtx, rtx);
593e4b17023SJohn Marino static rtx equiv_constant (rtx);
594e4b17023SJohn Marino static void record_jump_equiv (rtx, bool);
595e4b17023SJohn Marino static void record_jump_cond (enum rtx_code, enum machine_mode, rtx, rtx,
596e4b17023SJohn Marino int);
597e4b17023SJohn Marino static void cse_insn (rtx);
598e4b17023SJohn Marino static void cse_prescan_path (struct cse_basic_block_data *);
599e4b17023SJohn Marino static void invalidate_from_clobbers (rtx);
600e4b17023SJohn Marino static rtx cse_process_notes (rtx, rtx, bool *);
601e4b17023SJohn Marino static void cse_extended_basic_block (struct cse_basic_block_data *);
602e4b17023SJohn Marino static void count_reg_usage (rtx, int *, rtx, int);
603e4b17023SJohn Marino static int check_for_label_ref (rtx *, void *);
604e4b17023SJohn Marino extern void dump_class (struct table_elt*);
605e4b17023SJohn Marino static void get_cse_reg_info_1 (unsigned int regno);
606e4b17023SJohn Marino static struct cse_reg_info * get_cse_reg_info (unsigned int regno);
607e4b17023SJohn Marino static int check_dependence (rtx *, void *);
608e4b17023SJohn Marino
609e4b17023SJohn Marino static void flush_hash_table (void);
610e4b17023SJohn Marino static bool insn_live_p (rtx, int *);
611e4b17023SJohn Marino static bool set_live_p (rtx, rtx, int *);
612e4b17023SJohn Marino static int cse_change_cc_mode (rtx *, void *);
613e4b17023SJohn Marino static void cse_change_cc_mode_insn (rtx, rtx);
614e4b17023SJohn Marino static void cse_change_cc_mode_insns (rtx, rtx, rtx);
615e4b17023SJohn Marino static enum machine_mode cse_cc_succs (basic_block, basic_block, rtx, rtx,
616e4b17023SJohn Marino bool);
617e4b17023SJohn Marino
618e4b17023SJohn Marino
619e4b17023SJohn Marino #undef RTL_HOOKS_GEN_LOWPART
620e4b17023SJohn Marino #define RTL_HOOKS_GEN_LOWPART gen_lowpart_if_possible
621e4b17023SJohn Marino
622e4b17023SJohn Marino static const struct rtl_hooks cse_rtl_hooks = RTL_HOOKS_INITIALIZER;
623e4b17023SJohn Marino
624e4b17023SJohn Marino /* Nonzero if X has the form (PLUS frame-pointer integer). We check for
625e4b17023SJohn Marino virtual regs here because the simplify_*_operation routines are called
626e4b17023SJohn Marino by integrate.c, which is called before virtual register instantiation. */
627e4b17023SJohn Marino
628e4b17023SJohn Marino static bool
fixed_base_plus_p(rtx x)629e4b17023SJohn Marino fixed_base_plus_p (rtx x)
630e4b17023SJohn Marino {
631e4b17023SJohn Marino switch (GET_CODE (x))
632e4b17023SJohn Marino {
633e4b17023SJohn Marino case REG:
634e4b17023SJohn Marino if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx)
635e4b17023SJohn Marino return true;
636e4b17023SJohn Marino if (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])
637e4b17023SJohn Marino return true;
638e4b17023SJohn Marino if (REGNO (x) >= FIRST_VIRTUAL_REGISTER
639e4b17023SJohn Marino && REGNO (x) <= LAST_VIRTUAL_REGISTER)
640e4b17023SJohn Marino return true;
641e4b17023SJohn Marino return false;
642e4b17023SJohn Marino
643e4b17023SJohn Marino case PLUS:
644e4b17023SJohn Marino if (!CONST_INT_P (XEXP (x, 1)))
645e4b17023SJohn Marino return false;
646e4b17023SJohn Marino return fixed_base_plus_p (XEXP (x, 0));
647e4b17023SJohn Marino
648e4b17023SJohn Marino default:
649e4b17023SJohn Marino return false;
650e4b17023SJohn Marino }
651e4b17023SJohn Marino }
652e4b17023SJohn Marino
653e4b17023SJohn Marino /* Dump the expressions in the equivalence class indicated by CLASSP.
654e4b17023SJohn Marino This function is used only for debugging. */
655e4b17023SJohn Marino void
dump_class(struct table_elt * classp)656e4b17023SJohn Marino dump_class (struct table_elt *classp)
657e4b17023SJohn Marino {
658e4b17023SJohn Marino struct table_elt *elt;
659e4b17023SJohn Marino
660e4b17023SJohn Marino fprintf (stderr, "Equivalence chain for ");
661e4b17023SJohn Marino print_rtl (stderr, classp->exp);
662e4b17023SJohn Marino fprintf (stderr, ": \n");
663e4b17023SJohn Marino
664e4b17023SJohn Marino for (elt = classp->first_same_value; elt; elt = elt->next_same_value)
665e4b17023SJohn Marino {
666e4b17023SJohn Marino print_rtl (stderr, elt->exp);
667e4b17023SJohn Marino fprintf (stderr, "\n");
668e4b17023SJohn Marino }
669e4b17023SJohn Marino }
670e4b17023SJohn Marino
671e4b17023SJohn Marino /* Subroutine of approx_reg_cost; called through for_each_rtx. */
672e4b17023SJohn Marino
673e4b17023SJohn Marino static int
approx_reg_cost_1(rtx * xp,void * data)674e4b17023SJohn Marino approx_reg_cost_1 (rtx *xp, void *data)
675e4b17023SJohn Marino {
676e4b17023SJohn Marino rtx x = *xp;
677e4b17023SJohn Marino int *cost_p = (int *) data;
678e4b17023SJohn Marino
679e4b17023SJohn Marino if (x && REG_P (x))
680e4b17023SJohn Marino {
681e4b17023SJohn Marino unsigned int regno = REGNO (x);
682e4b17023SJohn Marino
683e4b17023SJohn Marino if (! CHEAP_REGNO (regno))
684e4b17023SJohn Marino {
685e4b17023SJohn Marino if (regno < FIRST_PSEUDO_REGISTER)
686e4b17023SJohn Marino {
687e4b17023SJohn Marino if (targetm.small_register_classes_for_mode_p (GET_MODE (x)))
688e4b17023SJohn Marino return 1;
689e4b17023SJohn Marino *cost_p += 2;
690e4b17023SJohn Marino }
691e4b17023SJohn Marino else
692e4b17023SJohn Marino *cost_p += 1;
693e4b17023SJohn Marino }
694e4b17023SJohn Marino }
695e4b17023SJohn Marino
696e4b17023SJohn Marino return 0;
697e4b17023SJohn Marino }
698e4b17023SJohn Marino
699e4b17023SJohn Marino /* Return an estimate of the cost of the registers used in an rtx.
700e4b17023SJohn Marino This is mostly the number of different REG expressions in the rtx;
701e4b17023SJohn Marino however for some exceptions like fixed registers we use a cost of
702e4b17023SJohn Marino 0. If any other hard register reference occurs, return MAX_COST. */
703e4b17023SJohn Marino
704e4b17023SJohn Marino static int
approx_reg_cost(rtx x)705e4b17023SJohn Marino approx_reg_cost (rtx x)
706e4b17023SJohn Marino {
707e4b17023SJohn Marino int cost = 0;
708e4b17023SJohn Marino
709e4b17023SJohn Marino if (for_each_rtx (&x, approx_reg_cost_1, (void *) &cost))
710e4b17023SJohn Marino return MAX_COST;
711e4b17023SJohn Marino
712e4b17023SJohn Marino return cost;
713e4b17023SJohn Marino }
714e4b17023SJohn Marino
715e4b17023SJohn Marino /* Return a negative value if an rtx A, whose costs are given by COST_A
716e4b17023SJohn Marino and REGCOST_A, is more desirable than an rtx B.
717e4b17023SJohn Marino Return a positive value if A is less desirable, or 0 if the two are
718e4b17023SJohn Marino equally good. */
719e4b17023SJohn Marino static int
preferable(int cost_a,int regcost_a,int cost_b,int regcost_b)720e4b17023SJohn Marino preferable (int cost_a, int regcost_a, int cost_b, int regcost_b)
721e4b17023SJohn Marino {
722e4b17023SJohn Marino /* First, get rid of cases involving expressions that are entirely
723e4b17023SJohn Marino unwanted. */
724e4b17023SJohn Marino if (cost_a != cost_b)
725e4b17023SJohn Marino {
726e4b17023SJohn Marino if (cost_a == MAX_COST)
727e4b17023SJohn Marino return 1;
728e4b17023SJohn Marino if (cost_b == MAX_COST)
729e4b17023SJohn Marino return -1;
730e4b17023SJohn Marino }
731e4b17023SJohn Marino
732e4b17023SJohn Marino /* Avoid extending lifetimes of hardregs. */
733e4b17023SJohn Marino if (regcost_a != regcost_b)
734e4b17023SJohn Marino {
735e4b17023SJohn Marino if (regcost_a == MAX_COST)
736e4b17023SJohn Marino return 1;
737e4b17023SJohn Marino if (regcost_b == MAX_COST)
738e4b17023SJohn Marino return -1;
739e4b17023SJohn Marino }
740e4b17023SJohn Marino
741e4b17023SJohn Marino /* Normal operation costs take precedence. */
742e4b17023SJohn Marino if (cost_a != cost_b)
743e4b17023SJohn Marino return cost_a - cost_b;
744e4b17023SJohn Marino /* Only if these are identical consider effects on register pressure. */
745e4b17023SJohn Marino if (regcost_a != regcost_b)
746e4b17023SJohn Marino return regcost_a - regcost_b;
747e4b17023SJohn Marino return 0;
748e4b17023SJohn Marino }
749e4b17023SJohn Marino
750e4b17023SJohn Marino /* Internal function, to compute cost when X is not a register; called
751e4b17023SJohn Marino from COST macro to keep it simple. */
752e4b17023SJohn Marino
753e4b17023SJohn Marino static int
notreg_cost(rtx x,enum rtx_code outer,int opno)754e4b17023SJohn Marino notreg_cost (rtx x, enum rtx_code outer, int opno)
755e4b17023SJohn Marino {
756e4b17023SJohn Marino return ((GET_CODE (x) == SUBREG
757e4b17023SJohn Marino && REG_P (SUBREG_REG (x))
758e4b17023SJohn Marino && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT
759e4b17023SJohn Marino && GET_MODE_CLASS (GET_MODE (SUBREG_REG (x))) == MODE_INT
760e4b17023SJohn Marino && (GET_MODE_SIZE (GET_MODE (x))
761e4b17023SJohn Marino < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
762e4b17023SJohn Marino && subreg_lowpart_p (x)
763e4b17023SJohn Marino && TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (x),
764e4b17023SJohn Marino GET_MODE (SUBREG_REG (x))))
765e4b17023SJohn Marino ? 0
766e4b17023SJohn Marino : rtx_cost (x, outer, opno, optimize_this_for_speed_p) * 2);
767e4b17023SJohn Marino }
768e4b17023SJohn Marino
769e4b17023SJohn Marino
770e4b17023SJohn Marino /* Initialize CSE_REG_INFO_TABLE. */
771e4b17023SJohn Marino
772e4b17023SJohn Marino static void
init_cse_reg_info(unsigned int nregs)773e4b17023SJohn Marino init_cse_reg_info (unsigned int nregs)
774e4b17023SJohn Marino {
775e4b17023SJohn Marino /* Do we need to grow the table? */
776e4b17023SJohn Marino if (nregs > cse_reg_info_table_size)
777e4b17023SJohn Marino {
778e4b17023SJohn Marino unsigned int new_size;
779e4b17023SJohn Marino
780e4b17023SJohn Marino if (cse_reg_info_table_size < 2048)
781e4b17023SJohn Marino {
782e4b17023SJohn Marino /* Compute a new size that is a power of 2 and no smaller
783e4b17023SJohn Marino than the large of NREGS and 64. */
784e4b17023SJohn Marino new_size = (cse_reg_info_table_size
785e4b17023SJohn Marino ? cse_reg_info_table_size : 64);
786e4b17023SJohn Marino
787e4b17023SJohn Marino while (new_size < nregs)
788e4b17023SJohn Marino new_size *= 2;
789e4b17023SJohn Marino }
790e4b17023SJohn Marino else
791e4b17023SJohn Marino {
792e4b17023SJohn Marino /* If we need a big table, allocate just enough to hold
793e4b17023SJohn Marino NREGS registers. */
794e4b17023SJohn Marino new_size = nregs;
795e4b17023SJohn Marino }
796e4b17023SJohn Marino
797e4b17023SJohn Marino /* Reallocate the table with NEW_SIZE entries. */
798e4b17023SJohn Marino free (cse_reg_info_table);
799e4b17023SJohn Marino cse_reg_info_table = XNEWVEC (struct cse_reg_info, new_size);
800e4b17023SJohn Marino cse_reg_info_table_size = new_size;
801e4b17023SJohn Marino cse_reg_info_table_first_uninitialized = 0;
802e4b17023SJohn Marino }
803e4b17023SJohn Marino
804e4b17023SJohn Marino /* Do we have all of the first NREGS entries initialized? */
805e4b17023SJohn Marino if (cse_reg_info_table_first_uninitialized < nregs)
806e4b17023SJohn Marino {
807e4b17023SJohn Marino unsigned int old_timestamp = cse_reg_info_timestamp - 1;
808e4b17023SJohn Marino unsigned int i;
809e4b17023SJohn Marino
810e4b17023SJohn Marino /* Put the old timestamp on newly allocated entries so that they
811e4b17023SJohn Marino will all be considered out of date. We do not touch those
812e4b17023SJohn Marino entries beyond the first NREGS entries to be nice to the
813e4b17023SJohn Marino virtual memory. */
814e4b17023SJohn Marino for (i = cse_reg_info_table_first_uninitialized; i < nregs; i++)
815e4b17023SJohn Marino cse_reg_info_table[i].timestamp = old_timestamp;
816e4b17023SJohn Marino
817e4b17023SJohn Marino cse_reg_info_table_first_uninitialized = nregs;
818e4b17023SJohn Marino }
819e4b17023SJohn Marino }
820e4b17023SJohn Marino
821e4b17023SJohn Marino /* Given REGNO, initialize the cse_reg_info entry for REGNO. */
822e4b17023SJohn Marino
823e4b17023SJohn Marino static void
get_cse_reg_info_1(unsigned int regno)824e4b17023SJohn Marino get_cse_reg_info_1 (unsigned int regno)
825e4b17023SJohn Marino {
826e4b17023SJohn Marino /* Set TIMESTAMP field to CSE_REG_INFO_TIMESTAMP so that this
827e4b17023SJohn Marino entry will be considered to have been initialized. */
828e4b17023SJohn Marino cse_reg_info_table[regno].timestamp = cse_reg_info_timestamp;
829e4b17023SJohn Marino
830e4b17023SJohn Marino /* Initialize the rest of the entry. */
831e4b17023SJohn Marino cse_reg_info_table[regno].reg_tick = 1;
832e4b17023SJohn Marino cse_reg_info_table[regno].reg_in_table = -1;
833e4b17023SJohn Marino cse_reg_info_table[regno].subreg_ticked = -1;
834e4b17023SJohn Marino cse_reg_info_table[regno].reg_qty = -regno - 1;
835e4b17023SJohn Marino }
836e4b17023SJohn Marino
837e4b17023SJohn Marino /* Find a cse_reg_info entry for REGNO. */
838e4b17023SJohn Marino
839e4b17023SJohn Marino static inline struct cse_reg_info *
get_cse_reg_info(unsigned int regno)840e4b17023SJohn Marino get_cse_reg_info (unsigned int regno)
841e4b17023SJohn Marino {
842e4b17023SJohn Marino struct cse_reg_info *p = &cse_reg_info_table[regno];
843e4b17023SJohn Marino
844e4b17023SJohn Marino /* If this entry has not been initialized, go ahead and initialize
845e4b17023SJohn Marino it. */
846e4b17023SJohn Marino if (p->timestamp != cse_reg_info_timestamp)
847e4b17023SJohn Marino get_cse_reg_info_1 (regno);
848e4b17023SJohn Marino
849e4b17023SJohn Marino return p;
850e4b17023SJohn Marino }
851e4b17023SJohn Marino
852e4b17023SJohn Marino /* Clear the hash table and initialize each register with its own quantity,
853e4b17023SJohn Marino for a new basic block. */
854e4b17023SJohn Marino
855e4b17023SJohn Marino static void
new_basic_block(void)856e4b17023SJohn Marino new_basic_block (void)
857e4b17023SJohn Marino {
858e4b17023SJohn Marino int i;
859e4b17023SJohn Marino
860e4b17023SJohn Marino next_qty = 0;
861e4b17023SJohn Marino
862e4b17023SJohn Marino /* Invalidate cse_reg_info_table. */
863e4b17023SJohn Marino cse_reg_info_timestamp++;
864e4b17023SJohn Marino
865e4b17023SJohn Marino /* Clear out hash table state for this pass. */
866e4b17023SJohn Marino CLEAR_HARD_REG_SET (hard_regs_in_table);
867e4b17023SJohn Marino
868e4b17023SJohn Marino /* The per-quantity values used to be initialized here, but it is
869e4b17023SJohn Marino much faster to initialize each as it is made in `make_new_qty'. */
870e4b17023SJohn Marino
871e4b17023SJohn Marino for (i = 0; i < HASH_SIZE; i++)
872e4b17023SJohn Marino {
873e4b17023SJohn Marino struct table_elt *first;
874e4b17023SJohn Marino
875e4b17023SJohn Marino first = table[i];
876e4b17023SJohn Marino if (first != NULL)
877e4b17023SJohn Marino {
878e4b17023SJohn Marino struct table_elt *last = first;
879e4b17023SJohn Marino
880e4b17023SJohn Marino table[i] = NULL;
881e4b17023SJohn Marino
882e4b17023SJohn Marino while (last->next_same_hash != NULL)
883e4b17023SJohn Marino last = last->next_same_hash;
884e4b17023SJohn Marino
885e4b17023SJohn Marino /* Now relink this hash entire chain into
886e4b17023SJohn Marino the free element list. */
887e4b17023SJohn Marino
888e4b17023SJohn Marino last->next_same_hash = free_element_chain;
889e4b17023SJohn Marino free_element_chain = first;
890e4b17023SJohn Marino }
891e4b17023SJohn Marino }
892e4b17023SJohn Marino
893e4b17023SJohn Marino #ifdef HAVE_cc0
894e4b17023SJohn Marino prev_insn_cc0 = 0;
895e4b17023SJohn Marino #endif
896e4b17023SJohn Marino }
897e4b17023SJohn Marino
898e4b17023SJohn Marino /* Say that register REG contains a quantity in mode MODE not in any
899e4b17023SJohn Marino register before and initialize that quantity. */
900e4b17023SJohn Marino
901e4b17023SJohn Marino static void
make_new_qty(unsigned int reg,enum machine_mode mode)902e4b17023SJohn Marino make_new_qty (unsigned int reg, enum machine_mode mode)
903e4b17023SJohn Marino {
904e4b17023SJohn Marino int q;
905e4b17023SJohn Marino struct qty_table_elem *ent;
906e4b17023SJohn Marino struct reg_eqv_elem *eqv;
907e4b17023SJohn Marino
908e4b17023SJohn Marino gcc_assert (next_qty < max_qty);
909e4b17023SJohn Marino
910e4b17023SJohn Marino q = REG_QTY (reg) = next_qty++;
911e4b17023SJohn Marino ent = &qty_table[q];
912e4b17023SJohn Marino ent->first_reg = reg;
913e4b17023SJohn Marino ent->last_reg = reg;
914e4b17023SJohn Marino ent->mode = mode;
915e4b17023SJohn Marino ent->const_rtx = ent->const_insn = NULL_RTX;
916e4b17023SJohn Marino ent->comparison_code = UNKNOWN;
917e4b17023SJohn Marino
918e4b17023SJohn Marino eqv = ®_eqv_table[reg];
919e4b17023SJohn Marino eqv->next = eqv->prev = -1;
920e4b17023SJohn Marino }
921e4b17023SJohn Marino
922e4b17023SJohn Marino /* Make reg NEW equivalent to reg OLD.
923e4b17023SJohn Marino OLD is not changing; NEW is. */
924e4b17023SJohn Marino
925e4b17023SJohn Marino static void
make_regs_eqv(unsigned int new_reg,unsigned int old_reg)926e4b17023SJohn Marino make_regs_eqv (unsigned int new_reg, unsigned int old_reg)
927e4b17023SJohn Marino {
928e4b17023SJohn Marino unsigned int lastr, firstr;
929e4b17023SJohn Marino int q = REG_QTY (old_reg);
930e4b17023SJohn Marino struct qty_table_elem *ent;
931e4b17023SJohn Marino
932e4b17023SJohn Marino ent = &qty_table[q];
933e4b17023SJohn Marino
934e4b17023SJohn Marino /* Nothing should become eqv until it has a "non-invalid" qty number. */
935e4b17023SJohn Marino gcc_assert (REGNO_QTY_VALID_P (old_reg));
936e4b17023SJohn Marino
937e4b17023SJohn Marino REG_QTY (new_reg) = q;
938e4b17023SJohn Marino firstr = ent->first_reg;
939e4b17023SJohn Marino lastr = ent->last_reg;
940e4b17023SJohn Marino
941e4b17023SJohn Marino /* Prefer fixed hard registers to anything. Prefer pseudo regs to other
942e4b17023SJohn Marino hard regs. Among pseudos, if NEW will live longer than any other reg
943e4b17023SJohn Marino of the same qty, and that is beyond the current basic block,
944e4b17023SJohn Marino make it the new canonical replacement for this qty. */
945e4b17023SJohn Marino if (! (firstr < FIRST_PSEUDO_REGISTER && FIXED_REGNO_P (firstr))
946e4b17023SJohn Marino /* Certain fixed registers might be of the class NO_REGS. This means
947e4b17023SJohn Marino that not only can they not be allocated by the compiler, but
948e4b17023SJohn Marino they cannot be used in substitutions or canonicalizations
949e4b17023SJohn Marino either. */
950e4b17023SJohn Marino && (new_reg >= FIRST_PSEUDO_REGISTER || REGNO_REG_CLASS (new_reg) != NO_REGS)
951e4b17023SJohn Marino && ((new_reg < FIRST_PSEUDO_REGISTER && FIXED_REGNO_P (new_reg))
952e4b17023SJohn Marino || (new_reg >= FIRST_PSEUDO_REGISTER
953e4b17023SJohn Marino && (firstr < FIRST_PSEUDO_REGISTER
954e4b17023SJohn Marino || (bitmap_bit_p (cse_ebb_live_out, new_reg)
955e4b17023SJohn Marino && !bitmap_bit_p (cse_ebb_live_out, firstr))
956e4b17023SJohn Marino || (bitmap_bit_p (cse_ebb_live_in, new_reg)
957e4b17023SJohn Marino && !bitmap_bit_p (cse_ebb_live_in, firstr))))))
958e4b17023SJohn Marino {
959e4b17023SJohn Marino reg_eqv_table[firstr].prev = new_reg;
960e4b17023SJohn Marino reg_eqv_table[new_reg].next = firstr;
961e4b17023SJohn Marino reg_eqv_table[new_reg].prev = -1;
962e4b17023SJohn Marino ent->first_reg = new_reg;
963e4b17023SJohn Marino }
964e4b17023SJohn Marino else
965e4b17023SJohn Marino {
966e4b17023SJohn Marino /* If NEW is a hard reg (known to be non-fixed), insert at end.
967e4b17023SJohn Marino Otherwise, insert before any non-fixed hard regs that are at the
968e4b17023SJohn Marino end. Registers of class NO_REGS cannot be used as an
969e4b17023SJohn Marino equivalent for anything. */
970e4b17023SJohn Marino while (lastr < FIRST_PSEUDO_REGISTER && reg_eqv_table[lastr].prev >= 0
971e4b17023SJohn Marino && (REGNO_REG_CLASS (lastr) == NO_REGS || ! FIXED_REGNO_P (lastr))
972e4b17023SJohn Marino && new_reg >= FIRST_PSEUDO_REGISTER)
973e4b17023SJohn Marino lastr = reg_eqv_table[lastr].prev;
974e4b17023SJohn Marino reg_eqv_table[new_reg].next = reg_eqv_table[lastr].next;
975e4b17023SJohn Marino if (reg_eqv_table[lastr].next >= 0)
976e4b17023SJohn Marino reg_eqv_table[reg_eqv_table[lastr].next].prev = new_reg;
977e4b17023SJohn Marino else
978e4b17023SJohn Marino qty_table[q].last_reg = new_reg;
979e4b17023SJohn Marino reg_eqv_table[lastr].next = new_reg;
980e4b17023SJohn Marino reg_eqv_table[new_reg].prev = lastr;
981e4b17023SJohn Marino }
982e4b17023SJohn Marino }
983e4b17023SJohn Marino
984e4b17023SJohn Marino /* Remove REG from its equivalence class. */
985e4b17023SJohn Marino
986e4b17023SJohn Marino static void
delete_reg_equiv(unsigned int reg)987e4b17023SJohn Marino delete_reg_equiv (unsigned int reg)
988e4b17023SJohn Marino {
989e4b17023SJohn Marino struct qty_table_elem *ent;
990e4b17023SJohn Marino int q = REG_QTY (reg);
991e4b17023SJohn Marino int p, n;
992e4b17023SJohn Marino
993e4b17023SJohn Marino /* If invalid, do nothing. */
994e4b17023SJohn Marino if (! REGNO_QTY_VALID_P (reg))
995e4b17023SJohn Marino return;
996e4b17023SJohn Marino
997e4b17023SJohn Marino ent = &qty_table[q];
998e4b17023SJohn Marino
999e4b17023SJohn Marino p = reg_eqv_table[reg].prev;
1000e4b17023SJohn Marino n = reg_eqv_table[reg].next;
1001e4b17023SJohn Marino
1002e4b17023SJohn Marino if (n != -1)
1003e4b17023SJohn Marino reg_eqv_table[n].prev = p;
1004e4b17023SJohn Marino else
1005e4b17023SJohn Marino ent->last_reg = p;
1006e4b17023SJohn Marino if (p != -1)
1007e4b17023SJohn Marino reg_eqv_table[p].next = n;
1008e4b17023SJohn Marino else
1009e4b17023SJohn Marino ent->first_reg = n;
1010e4b17023SJohn Marino
1011e4b17023SJohn Marino REG_QTY (reg) = -reg - 1;
1012e4b17023SJohn Marino }
1013e4b17023SJohn Marino
1014e4b17023SJohn Marino /* Remove any invalid expressions from the hash table
1015e4b17023SJohn Marino that refer to any of the registers contained in expression X.
1016e4b17023SJohn Marino
1017e4b17023SJohn Marino Make sure that newly inserted references to those registers
1018e4b17023SJohn Marino as subexpressions will be considered valid.
1019e4b17023SJohn Marino
1020e4b17023SJohn Marino mention_regs is not called when a register itself
1021e4b17023SJohn Marino is being stored in the table.
1022e4b17023SJohn Marino
1023e4b17023SJohn Marino Return 1 if we have done something that may have changed the hash code
1024e4b17023SJohn Marino of X. */
1025e4b17023SJohn Marino
1026e4b17023SJohn Marino static int
mention_regs(rtx x)1027e4b17023SJohn Marino mention_regs (rtx x)
1028e4b17023SJohn Marino {
1029e4b17023SJohn Marino enum rtx_code code;
1030e4b17023SJohn Marino int i, j;
1031e4b17023SJohn Marino const char *fmt;
1032e4b17023SJohn Marino int changed = 0;
1033e4b17023SJohn Marino
1034e4b17023SJohn Marino if (x == 0)
1035e4b17023SJohn Marino return 0;
1036e4b17023SJohn Marino
1037e4b17023SJohn Marino code = GET_CODE (x);
1038e4b17023SJohn Marino if (code == REG)
1039e4b17023SJohn Marino {
1040e4b17023SJohn Marino unsigned int regno = REGNO (x);
1041e4b17023SJohn Marino unsigned int endregno = END_REGNO (x);
1042e4b17023SJohn Marino unsigned int i;
1043e4b17023SJohn Marino
1044e4b17023SJohn Marino for (i = regno; i < endregno; i++)
1045e4b17023SJohn Marino {
1046e4b17023SJohn Marino if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
1047e4b17023SJohn Marino remove_invalid_refs (i);
1048e4b17023SJohn Marino
1049e4b17023SJohn Marino REG_IN_TABLE (i) = REG_TICK (i);
1050e4b17023SJohn Marino SUBREG_TICKED (i) = -1;
1051e4b17023SJohn Marino }
1052e4b17023SJohn Marino
1053e4b17023SJohn Marino return 0;
1054e4b17023SJohn Marino }
1055e4b17023SJohn Marino
1056e4b17023SJohn Marino /* If this is a SUBREG, we don't want to discard other SUBREGs of the same
1057e4b17023SJohn Marino pseudo if they don't use overlapping words. We handle only pseudos
1058e4b17023SJohn Marino here for simplicity. */
1059e4b17023SJohn Marino if (code == SUBREG && REG_P (SUBREG_REG (x))
1060e4b17023SJohn Marino && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
1061e4b17023SJohn Marino {
1062e4b17023SJohn Marino unsigned int i = REGNO (SUBREG_REG (x));
1063e4b17023SJohn Marino
1064e4b17023SJohn Marino if (REG_IN_TABLE (i) >= 0 && REG_IN_TABLE (i) != REG_TICK (i))
1065e4b17023SJohn Marino {
1066e4b17023SJohn Marino /* If REG_IN_TABLE (i) differs from REG_TICK (i) by one, and
1067e4b17023SJohn Marino the last store to this register really stored into this
1068e4b17023SJohn Marino subreg, then remove the memory of this subreg.
1069e4b17023SJohn Marino Otherwise, remove any memory of the entire register and
1070e4b17023SJohn Marino all its subregs from the table. */
1071e4b17023SJohn Marino if (REG_TICK (i) - REG_IN_TABLE (i) > 1
1072e4b17023SJohn Marino || SUBREG_TICKED (i) != REGNO (SUBREG_REG (x)))
1073e4b17023SJohn Marino remove_invalid_refs (i);
1074e4b17023SJohn Marino else
1075e4b17023SJohn Marino remove_invalid_subreg_refs (i, SUBREG_BYTE (x), GET_MODE (x));
1076e4b17023SJohn Marino }
1077e4b17023SJohn Marino
1078e4b17023SJohn Marino REG_IN_TABLE (i) = REG_TICK (i);
1079e4b17023SJohn Marino SUBREG_TICKED (i) = REGNO (SUBREG_REG (x));
1080e4b17023SJohn Marino return 0;
1081e4b17023SJohn Marino }
1082e4b17023SJohn Marino
1083e4b17023SJohn Marino /* If X is a comparison or a COMPARE and either operand is a register
1084e4b17023SJohn Marino that does not have a quantity, give it one. This is so that a later
1085e4b17023SJohn Marino call to record_jump_equiv won't cause X to be assigned a different
1086e4b17023SJohn Marino hash code and not found in the table after that call.
1087e4b17023SJohn Marino
1088e4b17023SJohn Marino It is not necessary to do this here, since rehash_using_reg can
1089e4b17023SJohn Marino fix up the table later, but doing this here eliminates the need to
1090e4b17023SJohn Marino call that expensive function in the most common case where the only
1091e4b17023SJohn Marino use of the register is in the comparison. */
1092e4b17023SJohn Marino
1093e4b17023SJohn Marino if (code == COMPARE || COMPARISON_P (x))
1094e4b17023SJohn Marino {
1095e4b17023SJohn Marino if (REG_P (XEXP (x, 0))
1096e4b17023SJohn Marino && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0))))
1097e4b17023SJohn Marino if (insert_regs (XEXP (x, 0), NULL, 0))
1098e4b17023SJohn Marino {
1099e4b17023SJohn Marino rehash_using_reg (XEXP (x, 0));
1100e4b17023SJohn Marino changed = 1;
1101e4b17023SJohn Marino }
1102e4b17023SJohn Marino
1103e4b17023SJohn Marino if (REG_P (XEXP (x, 1))
1104e4b17023SJohn Marino && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 1))))
1105e4b17023SJohn Marino if (insert_regs (XEXP (x, 1), NULL, 0))
1106e4b17023SJohn Marino {
1107e4b17023SJohn Marino rehash_using_reg (XEXP (x, 1));
1108e4b17023SJohn Marino changed = 1;
1109e4b17023SJohn Marino }
1110e4b17023SJohn Marino }
1111e4b17023SJohn Marino
1112e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
1113e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
1114e4b17023SJohn Marino if (fmt[i] == 'e')
1115e4b17023SJohn Marino changed |= mention_regs (XEXP (x, i));
1116e4b17023SJohn Marino else if (fmt[i] == 'E')
1117e4b17023SJohn Marino for (j = 0; j < XVECLEN (x, i); j++)
1118e4b17023SJohn Marino changed |= mention_regs (XVECEXP (x, i, j));
1119e4b17023SJohn Marino
1120e4b17023SJohn Marino return changed;
1121e4b17023SJohn Marino }
1122e4b17023SJohn Marino
1123e4b17023SJohn Marino /* Update the register quantities for inserting X into the hash table
1124e4b17023SJohn Marino with a value equivalent to CLASSP.
1125e4b17023SJohn Marino (If the class does not contain a REG, it is irrelevant.)
1126e4b17023SJohn Marino If MODIFIED is nonzero, X is a destination; it is being modified.
1127e4b17023SJohn Marino Note that delete_reg_equiv should be called on a register
1128e4b17023SJohn Marino before insert_regs is done on that register with MODIFIED != 0.
1129e4b17023SJohn Marino
1130e4b17023SJohn Marino Nonzero value means that elements of reg_qty have changed
1131e4b17023SJohn Marino so X's hash code may be different. */
1132e4b17023SJohn Marino
1133e4b17023SJohn Marino static int
insert_regs(rtx x,struct table_elt * classp,int modified)1134e4b17023SJohn Marino insert_regs (rtx x, struct table_elt *classp, int modified)
1135e4b17023SJohn Marino {
1136e4b17023SJohn Marino if (REG_P (x))
1137e4b17023SJohn Marino {
1138e4b17023SJohn Marino unsigned int regno = REGNO (x);
1139e4b17023SJohn Marino int qty_valid;
1140e4b17023SJohn Marino
1141e4b17023SJohn Marino /* If REGNO is in the equivalence table already but is of the
1142e4b17023SJohn Marino wrong mode for that equivalence, don't do anything here. */
1143e4b17023SJohn Marino
1144e4b17023SJohn Marino qty_valid = REGNO_QTY_VALID_P (regno);
1145e4b17023SJohn Marino if (qty_valid)
1146e4b17023SJohn Marino {
1147e4b17023SJohn Marino struct qty_table_elem *ent = &qty_table[REG_QTY (regno)];
1148e4b17023SJohn Marino
1149e4b17023SJohn Marino if (ent->mode != GET_MODE (x))
1150e4b17023SJohn Marino return 0;
1151e4b17023SJohn Marino }
1152e4b17023SJohn Marino
1153e4b17023SJohn Marino if (modified || ! qty_valid)
1154e4b17023SJohn Marino {
1155e4b17023SJohn Marino if (classp)
1156e4b17023SJohn Marino for (classp = classp->first_same_value;
1157e4b17023SJohn Marino classp != 0;
1158e4b17023SJohn Marino classp = classp->next_same_value)
1159e4b17023SJohn Marino if (REG_P (classp->exp)
1160e4b17023SJohn Marino && GET_MODE (classp->exp) == GET_MODE (x))
1161e4b17023SJohn Marino {
1162e4b17023SJohn Marino unsigned c_regno = REGNO (classp->exp);
1163e4b17023SJohn Marino
1164e4b17023SJohn Marino gcc_assert (REGNO_QTY_VALID_P (c_regno));
1165e4b17023SJohn Marino
1166e4b17023SJohn Marino /* Suppose that 5 is hard reg and 100 and 101 are
1167e4b17023SJohn Marino pseudos. Consider
1168e4b17023SJohn Marino
1169e4b17023SJohn Marino (set (reg:si 100) (reg:si 5))
1170e4b17023SJohn Marino (set (reg:si 5) (reg:si 100))
1171e4b17023SJohn Marino (set (reg:di 101) (reg:di 5))
1172e4b17023SJohn Marino
1173e4b17023SJohn Marino We would now set REG_QTY (101) = REG_QTY (5), but the
1174e4b17023SJohn Marino entry for 5 is in SImode. When we use this later in
1175e4b17023SJohn Marino copy propagation, we get the register in wrong mode. */
1176e4b17023SJohn Marino if (qty_table[REG_QTY (c_regno)].mode != GET_MODE (x))
1177e4b17023SJohn Marino continue;
1178e4b17023SJohn Marino
1179e4b17023SJohn Marino make_regs_eqv (regno, c_regno);
1180e4b17023SJohn Marino return 1;
1181e4b17023SJohn Marino }
1182e4b17023SJohn Marino
1183e4b17023SJohn Marino /* Mention_regs for a SUBREG checks if REG_TICK is exactly one larger
1184e4b17023SJohn Marino than REG_IN_TABLE to find out if there was only a single preceding
1185e4b17023SJohn Marino invalidation - for the SUBREG - or another one, which would be
1186e4b17023SJohn Marino for the full register. However, if we find here that REG_TICK
1187e4b17023SJohn Marino indicates that the register is invalid, it means that it has
1188e4b17023SJohn Marino been invalidated in a separate operation. The SUBREG might be used
1189e4b17023SJohn Marino now (then this is a recursive call), or we might use the full REG
1190e4b17023SJohn Marino now and a SUBREG of it later. So bump up REG_TICK so that
1191e4b17023SJohn Marino mention_regs will do the right thing. */
1192e4b17023SJohn Marino if (! modified
1193e4b17023SJohn Marino && REG_IN_TABLE (regno) >= 0
1194e4b17023SJohn Marino && REG_TICK (regno) == REG_IN_TABLE (regno) + 1)
1195e4b17023SJohn Marino REG_TICK (regno)++;
1196e4b17023SJohn Marino make_new_qty (regno, GET_MODE (x));
1197e4b17023SJohn Marino return 1;
1198e4b17023SJohn Marino }
1199e4b17023SJohn Marino
1200e4b17023SJohn Marino return 0;
1201e4b17023SJohn Marino }
1202e4b17023SJohn Marino
1203e4b17023SJohn Marino /* If X is a SUBREG, we will likely be inserting the inner register in the
1204e4b17023SJohn Marino table. If that register doesn't have an assigned quantity number at
1205e4b17023SJohn Marino this point but does later, the insertion that we will be doing now will
1206e4b17023SJohn Marino not be accessible because its hash code will have changed. So assign
1207e4b17023SJohn Marino a quantity number now. */
1208e4b17023SJohn Marino
1209e4b17023SJohn Marino else if (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
1210e4b17023SJohn Marino && ! REGNO_QTY_VALID_P (REGNO (SUBREG_REG (x))))
1211e4b17023SJohn Marino {
1212e4b17023SJohn Marino insert_regs (SUBREG_REG (x), NULL, 0);
1213e4b17023SJohn Marino mention_regs (x);
1214e4b17023SJohn Marino return 1;
1215e4b17023SJohn Marino }
1216e4b17023SJohn Marino else
1217e4b17023SJohn Marino return mention_regs (x);
1218e4b17023SJohn Marino }
1219e4b17023SJohn Marino
1220e4b17023SJohn Marino
1221e4b17023SJohn Marino /* Compute upper and lower anchors for CST. Also compute the offset of CST
1222e4b17023SJohn Marino from these anchors/bases such that *_BASE + *_OFFS = CST. Return false iff
1223e4b17023SJohn Marino CST is equal to an anchor. */
1224e4b17023SJohn Marino
1225e4b17023SJohn Marino static bool
compute_const_anchors(rtx cst,HOST_WIDE_INT * lower_base,HOST_WIDE_INT * lower_offs,HOST_WIDE_INT * upper_base,HOST_WIDE_INT * upper_offs)1226e4b17023SJohn Marino compute_const_anchors (rtx cst,
1227e4b17023SJohn Marino HOST_WIDE_INT *lower_base, HOST_WIDE_INT *lower_offs,
1228e4b17023SJohn Marino HOST_WIDE_INT *upper_base, HOST_WIDE_INT *upper_offs)
1229e4b17023SJohn Marino {
1230e4b17023SJohn Marino HOST_WIDE_INT n = INTVAL (cst);
1231e4b17023SJohn Marino
1232e4b17023SJohn Marino *lower_base = n & ~(targetm.const_anchor - 1);
1233e4b17023SJohn Marino if (*lower_base == n)
1234e4b17023SJohn Marino return false;
1235e4b17023SJohn Marino
1236e4b17023SJohn Marino *upper_base =
1237e4b17023SJohn Marino (n + (targetm.const_anchor - 1)) & ~(targetm.const_anchor - 1);
1238e4b17023SJohn Marino *upper_offs = n - *upper_base;
1239e4b17023SJohn Marino *lower_offs = n - *lower_base;
1240e4b17023SJohn Marino return true;
1241e4b17023SJohn Marino }
1242e4b17023SJohn Marino
1243e4b17023SJohn Marino /* Insert the equivalence between ANCHOR and (REG + OFF) in mode MODE. */
1244e4b17023SJohn Marino
1245e4b17023SJohn Marino static void
insert_const_anchor(HOST_WIDE_INT anchor,rtx reg,HOST_WIDE_INT offs,enum machine_mode mode)1246e4b17023SJohn Marino insert_const_anchor (HOST_WIDE_INT anchor, rtx reg, HOST_WIDE_INT offs,
1247e4b17023SJohn Marino enum machine_mode mode)
1248e4b17023SJohn Marino {
1249e4b17023SJohn Marino struct table_elt *elt;
1250e4b17023SJohn Marino unsigned hash;
1251e4b17023SJohn Marino rtx anchor_exp;
1252e4b17023SJohn Marino rtx exp;
1253e4b17023SJohn Marino
1254e4b17023SJohn Marino anchor_exp = GEN_INT (anchor);
1255e4b17023SJohn Marino hash = HASH (anchor_exp, mode);
1256e4b17023SJohn Marino elt = lookup (anchor_exp, hash, mode);
1257e4b17023SJohn Marino if (!elt)
1258e4b17023SJohn Marino elt = insert (anchor_exp, NULL, hash, mode);
1259e4b17023SJohn Marino
1260e4b17023SJohn Marino exp = plus_constant (reg, offs);
1261e4b17023SJohn Marino /* REG has just been inserted and the hash codes recomputed. */
1262e4b17023SJohn Marino mention_regs (exp);
1263e4b17023SJohn Marino hash = HASH (exp, mode);
1264e4b17023SJohn Marino
1265e4b17023SJohn Marino /* Use the cost of the register rather than the whole expression. When
1266e4b17023SJohn Marino looking up constant anchors we will further offset the corresponding
1267e4b17023SJohn Marino expression therefore it does not make sense to prefer REGs over
1268e4b17023SJohn Marino reg-immediate additions. Prefer instead the oldest expression. Also
1269e4b17023SJohn Marino don't prefer pseudos over hard regs so that we derive constants in
1270e4b17023SJohn Marino argument registers from other argument registers rather than from the
1271e4b17023SJohn Marino original pseudo that was used to synthesize the constant. */
1272e4b17023SJohn Marino insert_with_costs (exp, elt, hash, mode, COST (reg), 1);
1273e4b17023SJohn Marino }
1274e4b17023SJohn Marino
1275e4b17023SJohn Marino /* The constant CST is equivalent to the register REG. Create
1276e4b17023SJohn Marino equivalences between the two anchors of CST and the corresponding
1277e4b17023SJohn Marino register-offset expressions using REG. */
1278e4b17023SJohn Marino
1279e4b17023SJohn Marino static void
insert_const_anchors(rtx reg,rtx cst,enum machine_mode mode)1280e4b17023SJohn Marino insert_const_anchors (rtx reg, rtx cst, enum machine_mode mode)
1281e4b17023SJohn Marino {
1282e4b17023SJohn Marino HOST_WIDE_INT lower_base, lower_offs, upper_base, upper_offs;
1283e4b17023SJohn Marino
1284e4b17023SJohn Marino if (!compute_const_anchors (cst, &lower_base, &lower_offs,
1285e4b17023SJohn Marino &upper_base, &upper_offs))
1286e4b17023SJohn Marino return;
1287e4b17023SJohn Marino
1288e4b17023SJohn Marino /* Ignore anchors of value 0. Constants accessible from zero are
1289e4b17023SJohn Marino simple. */
1290e4b17023SJohn Marino if (lower_base != 0)
1291e4b17023SJohn Marino insert_const_anchor (lower_base, reg, -lower_offs, mode);
1292e4b17023SJohn Marino
1293e4b17023SJohn Marino if (upper_base != 0)
1294e4b17023SJohn Marino insert_const_anchor (upper_base, reg, -upper_offs, mode);
1295e4b17023SJohn Marino }
1296e4b17023SJohn Marino
1297e4b17023SJohn Marino /* We need to express ANCHOR_ELT->exp + OFFS. Walk the equivalence list of
1298e4b17023SJohn Marino ANCHOR_ELT and see if offsetting any of the entries by OFFS would create a
1299e4b17023SJohn Marino valid expression. Return the cheapest and oldest of such expressions. In
1300e4b17023SJohn Marino *OLD, return how old the resulting expression is compared to the other
1301e4b17023SJohn Marino equivalent expressions. */
1302e4b17023SJohn Marino
1303e4b17023SJohn Marino static rtx
find_reg_offset_for_const(struct table_elt * anchor_elt,HOST_WIDE_INT offs,unsigned * old)1304e4b17023SJohn Marino find_reg_offset_for_const (struct table_elt *anchor_elt, HOST_WIDE_INT offs,
1305e4b17023SJohn Marino unsigned *old)
1306e4b17023SJohn Marino {
1307e4b17023SJohn Marino struct table_elt *elt;
1308e4b17023SJohn Marino unsigned idx;
1309e4b17023SJohn Marino struct table_elt *match_elt;
1310e4b17023SJohn Marino rtx match;
1311e4b17023SJohn Marino
1312e4b17023SJohn Marino /* Find the cheapest and *oldest* expression to maximize the chance of
1313e4b17023SJohn Marino reusing the same pseudo. */
1314e4b17023SJohn Marino
1315e4b17023SJohn Marino match_elt = NULL;
1316e4b17023SJohn Marino match = NULL_RTX;
1317e4b17023SJohn Marino for (elt = anchor_elt->first_same_value, idx = 0;
1318e4b17023SJohn Marino elt;
1319e4b17023SJohn Marino elt = elt->next_same_value, idx++)
1320e4b17023SJohn Marino {
1321e4b17023SJohn Marino if (match_elt && CHEAPER (match_elt, elt))
1322e4b17023SJohn Marino return match;
1323e4b17023SJohn Marino
1324e4b17023SJohn Marino if (REG_P (elt->exp)
1325e4b17023SJohn Marino || (GET_CODE (elt->exp) == PLUS
1326e4b17023SJohn Marino && REG_P (XEXP (elt->exp, 0))
1327e4b17023SJohn Marino && GET_CODE (XEXP (elt->exp, 1)) == CONST_INT))
1328e4b17023SJohn Marino {
1329e4b17023SJohn Marino rtx x;
1330e4b17023SJohn Marino
1331e4b17023SJohn Marino /* Ignore expressions that are no longer valid. */
1332e4b17023SJohn Marino if (!REG_P (elt->exp) && !exp_equiv_p (elt->exp, elt->exp, 1, false))
1333e4b17023SJohn Marino continue;
1334e4b17023SJohn Marino
1335e4b17023SJohn Marino x = plus_constant (elt->exp, offs);
1336e4b17023SJohn Marino if (REG_P (x)
1337e4b17023SJohn Marino || (GET_CODE (x) == PLUS
1338e4b17023SJohn Marino && IN_RANGE (INTVAL (XEXP (x, 1)),
1339e4b17023SJohn Marino -targetm.const_anchor,
1340e4b17023SJohn Marino targetm.const_anchor - 1)))
1341e4b17023SJohn Marino {
1342e4b17023SJohn Marino match = x;
1343e4b17023SJohn Marino match_elt = elt;
1344e4b17023SJohn Marino *old = idx;
1345e4b17023SJohn Marino }
1346e4b17023SJohn Marino }
1347e4b17023SJohn Marino }
1348e4b17023SJohn Marino
1349e4b17023SJohn Marino return match;
1350e4b17023SJohn Marino }
1351e4b17023SJohn Marino
1352e4b17023SJohn Marino /* Try to express the constant SRC_CONST using a register+offset expression
1353e4b17023SJohn Marino derived from a constant anchor. Return it if successful or NULL_RTX,
1354e4b17023SJohn Marino otherwise. */
1355e4b17023SJohn Marino
1356e4b17023SJohn Marino static rtx
try_const_anchors(rtx src_const,enum machine_mode mode)1357e4b17023SJohn Marino try_const_anchors (rtx src_const, enum machine_mode mode)
1358e4b17023SJohn Marino {
1359e4b17023SJohn Marino struct table_elt *lower_elt, *upper_elt;
1360e4b17023SJohn Marino HOST_WIDE_INT lower_base, lower_offs, upper_base, upper_offs;
1361e4b17023SJohn Marino rtx lower_anchor_rtx, upper_anchor_rtx;
1362e4b17023SJohn Marino rtx lower_exp = NULL_RTX, upper_exp = NULL_RTX;
1363e4b17023SJohn Marino unsigned lower_old, upper_old;
1364e4b17023SJohn Marino
1365e4b17023SJohn Marino if (!compute_const_anchors (src_const, &lower_base, &lower_offs,
1366e4b17023SJohn Marino &upper_base, &upper_offs))
1367e4b17023SJohn Marino return NULL_RTX;
1368e4b17023SJohn Marino
1369e4b17023SJohn Marino lower_anchor_rtx = GEN_INT (lower_base);
1370e4b17023SJohn Marino upper_anchor_rtx = GEN_INT (upper_base);
1371e4b17023SJohn Marino lower_elt = lookup (lower_anchor_rtx, HASH (lower_anchor_rtx, mode), mode);
1372e4b17023SJohn Marino upper_elt = lookup (upper_anchor_rtx, HASH (upper_anchor_rtx, mode), mode);
1373e4b17023SJohn Marino
1374e4b17023SJohn Marino if (lower_elt)
1375e4b17023SJohn Marino lower_exp = find_reg_offset_for_const (lower_elt, lower_offs, &lower_old);
1376e4b17023SJohn Marino if (upper_elt)
1377e4b17023SJohn Marino upper_exp = find_reg_offset_for_const (upper_elt, upper_offs, &upper_old);
1378e4b17023SJohn Marino
1379e4b17023SJohn Marino if (!lower_exp)
1380e4b17023SJohn Marino return upper_exp;
1381e4b17023SJohn Marino if (!upper_exp)
1382e4b17023SJohn Marino return lower_exp;
1383e4b17023SJohn Marino
1384e4b17023SJohn Marino /* Return the older expression. */
1385e4b17023SJohn Marino return (upper_old > lower_old ? upper_exp : lower_exp);
1386e4b17023SJohn Marino }
1387e4b17023SJohn Marino
1388e4b17023SJohn Marino /* Look in or update the hash table. */
1389e4b17023SJohn Marino
1390e4b17023SJohn Marino /* Remove table element ELT from use in the table.
1391e4b17023SJohn Marino HASH is its hash code, made using the HASH macro.
1392e4b17023SJohn Marino It's an argument because often that is known in advance
1393e4b17023SJohn Marino and we save much time not recomputing it. */
1394e4b17023SJohn Marino
1395e4b17023SJohn Marino static void
remove_from_table(struct table_elt * elt,unsigned int hash)1396e4b17023SJohn Marino remove_from_table (struct table_elt *elt, unsigned int hash)
1397e4b17023SJohn Marino {
1398e4b17023SJohn Marino if (elt == 0)
1399e4b17023SJohn Marino return;
1400e4b17023SJohn Marino
1401e4b17023SJohn Marino /* Mark this element as removed. See cse_insn. */
1402e4b17023SJohn Marino elt->first_same_value = 0;
1403e4b17023SJohn Marino
1404e4b17023SJohn Marino /* Remove the table element from its equivalence class. */
1405e4b17023SJohn Marino
1406e4b17023SJohn Marino {
1407e4b17023SJohn Marino struct table_elt *prev = elt->prev_same_value;
1408e4b17023SJohn Marino struct table_elt *next = elt->next_same_value;
1409e4b17023SJohn Marino
1410e4b17023SJohn Marino if (next)
1411e4b17023SJohn Marino next->prev_same_value = prev;
1412e4b17023SJohn Marino
1413e4b17023SJohn Marino if (prev)
1414e4b17023SJohn Marino prev->next_same_value = next;
1415e4b17023SJohn Marino else
1416e4b17023SJohn Marino {
1417e4b17023SJohn Marino struct table_elt *newfirst = next;
1418e4b17023SJohn Marino while (next)
1419e4b17023SJohn Marino {
1420e4b17023SJohn Marino next->first_same_value = newfirst;
1421e4b17023SJohn Marino next = next->next_same_value;
1422e4b17023SJohn Marino }
1423e4b17023SJohn Marino }
1424e4b17023SJohn Marino }
1425e4b17023SJohn Marino
1426e4b17023SJohn Marino /* Remove the table element from its hash bucket. */
1427e4b17023SJohn Marino
1428e4b17023SJohn Marino {
1429e4b17023SJohn Marino struct table_elt *prev = elt->prev_same_hash;
1430e4b17023SJohn Marino struct table_elt *next = elt->next_same_hash;
1431e4b17023SJohn Marino
1432e4b17023SJohn Marino if (next)
1433e4b17023SJohn Marino next->prev_same_hash = prev;
1434e4b17023SJohn Marino
1435e4b17023SJohn Marino if (prev)
1436e4b17023SJohn Marino prev->next_same_hash = next;
1437e4b17023SJohn Marino else if (table[hash] == elt)
1438e4b17023SJohn Marino table[hash] = next;
1439e4b17023SJohn Marino else
1440e4b17023SJohn Marino {
1441e4b17023SJohn Marino /* This entry is not in the proper hash bucket. This can happen
1442e4b17023SJohn Marino when two classes were merged by `merge_equiv_classes'. Search
1443e4b17023SJohn Marino for the hash bucket that it heads. This happens only very
1444e4b17023SJohn Marino rarely, so the cost is acceptable. */
1445e4b17023SJohn Marino for (hash = 0; hash < HASH_SIZE; hash++)
1446e4b17023SJohn Marino if (table[hash] == elt)
1447e4b17023SJohn Marino table[hash] = next;
1448e4b17023SJohn Marino }
1449e4b17023SJohn Marino }
1450e4b17023SJohn Marino
1451e4b17023SJohn Marino /* Remove the table element from its related-value circular chain. */
1452e4b17023SJohn Marino
1453e4b17023SJohn Marino if (elt->related_value != 0 && elt->related_value != elt)
1454e4b17023SJohn Marino {
1455e4b17023SJohn Marino struct table_elt *p = elt->related_value;
1456e4b17023SJohn Marino
1457e4b17023SJohn Marino while (p->related_value != elt)
1458e4b17023SJohn Marino p = p->related_value;
1459e4b17023SJohn Marino p->related_value = elt->related_value;
1460e4b17023SJohn Marino if (p->related_value == p)
1461e4b17023SJohn Marino p->related_value = 0;
1462e4b17023SJohn Marino }
1463e4b17023SJohn Marino
1464e4b17023SJohn Marino /* Now add it to the free element chain. */
1465e4b17023SJohn Marino elt->next_same_hash = free_element_chain;
1466e4b17023SJohn Marino free_element_chain = elt;
1467e4b17023SJohn Marino }
1468e4b17023SJohn Marino
1469e4b17023SJohn Marino /* Same as above, but X is a pseudo-register. */
1470e4b17023SJohn Marino
1471e4b17023SJohn Marino static void
remove_pseudo_from_table(rtx x,unsigned int hash)1472e4b17023SJohn Marino remove_pseudo_from_table (rtx x, unsigned int hash)
1473e4b17023SJohn Marino {
1474e4b17023SJohn Marino struct table_elt *elt;
1475e4b17023SJohn Marino
1476e4b17023SJohn Marino /* Because a pseudo-register can be referenced in more than one
1477e4b17023SJohn Marino mode, we might have to remove more than one table entry. */
1478e4b17023SJohn Marino while ((elt = lookup_for_remove (x, hash, VOIDmode)))
1479e4b17023SJohn Marino remove_from_table (elt, hash);
1480e4b17023SJohn Marino }
1481e4b17023SJohn Marino
1482e4b17023SJohn Marino /* Look up X in the hash table and return its table element,
1483e4b17023SJohn Marino or 0 if X is not in the table.
1484e4b17023SJohn Marino
1485e4b17023SJohn Marino MODE is the machine-mode of X, or if X is an integer constant
1486e4b17023SJohn Marino with VOIDmode then MODE is the mode with which X will be used.
1487e4b17023SJohn Marino
1488e4b17023SJohn Marino Here we are satisfied to find an expression whose tree structure
1489e4b17023SJohn Marino looks like X. */
1490e4b17023SJohn Marino
1491e4b17023SJohn Marino static struct table_elt *
lookup(rtx x,unsigned int hash,enum machine_mode mode)1492e4b17023SJohn Marino lookup (rtx x, unsigned int hash, enum machine_mode mode)
1493e4b17023SJohn Marino {
1494e4b17023SJohn Marino struct table_elt *p;
1495e4b17023SJohn Marino
1496e4b17023SJohn Marino for (p = table[hash]; p; p = p->next_same_hash)
1497e4b17023SJohn Marino if (mode == p->mode && ((x == p->exp && REG_P (x))
1498e4b17023SJohn Marino || exp_equiv_p (x, p->exp, !REG_P (x), false)))
1499e4b17023SJohn Marino return p;
1500e4b17023SJohn Marino
1501e4b17023SJohn Marino return 0;
1502e4b17023SJohn Marino }
1503e4b17023SJohn Marino
1504e4b17023SJohn Marino /* Like `lookup' but don't care whether the table element uses invalid regs.
1505e4b17023SJohn Marino Also ignore discrepancies in the machine mode of a register. */
1506e4b17023SJohn Marino
1507e4b17023SJohn Marino static struct table_elt *
lookup_for_remove(rtx x,unsigned int hash,enum machine_mode mode)1508e4b17023SJohn Marino lookup_for_remove (rtx x, unsigned int hash, enum machine_mode mode)
1509e4b17023SJohn Marino {
1510e4b17023SJohn Marino struct table_elt *p;
1511e4b17023SJohn Marino
1512e4b17023SJohn Marino if (REG_P (x))
1513e4b17023SJohn Marino {
1514e4b17023SJohn Marino unsigned int regno = REGNO (x);
1515e4b17023SJohn Marino
1516e4b17023SJohn Marino /* Don't check the machine mode when comparing registers;
1517e4b17023SJohn Marino invalidating (REG:SI 0) also invalidates (REG:DF 0). */
1518e4b17023SJohn Marino for (p = table[hash]; p; p = p->next_same_hash)
1519e4b17023SJohn Marino if (REG_P (p->exp)
1520e4b17023SJohn Marino && REGNO (p->exp) == regno)
1521e4b17023SJohn Marino return p;
1522e4b17023SJohn Marino }
1523e4b17023SJohn Marino else
1524e4b17023SJohn Marino {
1525e4b17023SJohn Marino for (p = table[hash]; p; p = p->next_same_hash)
1526e4b17023SJohn Marino if (mode == p->mode
1527e4b17023SJohn Marino && (x == p->exp || exp_equiv_p (x, p->exp, 0, false)))
1528e4b17023SJohn Marino return p;
1529e4b17023SJohn Marino }
1530e4b17023SJohn Marino
1531e4b17023SJohn Marino return 0;
1532e4b17023SJohn Marino }
1533e4b17023SJohn Marino
1534e4b17023SJohn Marino /* Look for an expression equivalent to X and with code CODE.
1535e4b17023SJohn Marino If one is found, return that expression. */
1536e4b17023SJohn Marino
1537e4b17023SJohn Marino static rtx
lookup_as_function(rtx x,enum rtx_code code)1538e4b17023SJohn Marino lookup_as_function (rtx x, enum rtx_code code)
1539e4b17023SJohn Marino {
1540e4b17023SJohn Marino struct table_elt *p
1541e4b17023SJohn Marino = lookup (x, SAFE_HASH (x, VOIDmode), GET_MODE (x));
1542e4b17023SJohn Marino
1543e4b17023SJohn Marino if (p == 0)
1544e4b17023SJohn Marino return 0;
1545e4b17023SJohn Marino
1546e4b17023SJohn Marino for (p = p->first_same_value; p; p = p->next_same_value)
1547e4b17023SJohn Marino if (GET_CODE (p->exp) == code
1548e4b17023SJohn Marino /* Make sure this is a valid entry in the table. */
1549e4b17023SJohn Marino && exp_equiv_p (p->exp, p->exp, 1, false))
1550e4b17023SJohn Marino return p->exp;
1551e4b17023SJohn Marino
1552e4b17023SJohn Marino return 0;
1553e4b17023SJohn Marino }
1554e4b17023SJohn Marino
1555e4b17023SJohn Marino /* Insert X in the hash table, assuming HASH is its hash code and
1556e4b17023SJohn Marino CLASSP is an element of the class it should go in (or 0 if a new
1557e4b17023SJohn Marino class should be made). COST is the code of X and reg_cost is the
1558e4b17023SJohn Marino cost of registers in X. It is inserted at the proper position to
1559e4b17023SJohn Marino keep the class in the order cheapest first.
1560e4b17023SJohn Marino
1561e4b17023SJohn Marino MODE is the machine-mode of X, or if X is an integer constant
1562e4b17023SJohn Marino with VOIDmode then MODE is the mode with which X will be used.
1563e4b17023SJohn Marino
1564e4b17023SJohn Marino For elements of equal cheapness, the most recent one
1565e4b17023SJohn Marino goes in front, except that the first element in the list
1566e4b17023SJohn Marino remains first unless a cheaper element is added. The order of
1567e4b17023SJohn Marino pseudo-registers does not matter, as canon_reg will be called to
1568e4b17023SJohn Marino find the cheapest when a register is retrieved from the table.
1569e4b17023SJohn Marino
1570e4b17023SJohn Marino The in_memory field in the hash table element is set to 0.
1571e4b17023SJohn Marino The caller must set it nonzero if appropriate.
1572e4b17023SJohn Marino
1573e4b17023SJohn Marino You should call insert_regs (X, CLASSP, MODIFY) before calling here,
1574e4b17023SJohn Marino and if insert_regs returns a nonzero value
1575e4b17023SJohn Marino you must then recompute its hash code before calling here.
1576e4b17023SJohn Marino
1577e4b17023SJohn Marino If necessary, update table showing constant values of quantities. */
1578e4b17023SJohn Marino
1579e4b17023SJohn Marino static struct table_elt *
insert_with_costs(rtx x,struct table_elt * classp,unsigned int hash,enum machine_mode mode,int cost,int reg_cost)1580e4b17023SJohn Marino insert_with_costs (rtx x, struct table_elt *classp, unsigned int hash,
1581e4b17023SJohn Marino enum machine_mode mode, int cost, int reg_cost)
1582e4b17023SJohn Marino {
1583e4b17023SJohn Marino struct table_elt *elt;
1584e4b17023SJohn Marino
1585e4b17023SJohn Marino /* If X is a register and we haven't made a quantity for it,
1586e4b17023SJohn Marino something is wrong. */
1587e4b17023SJohn Marino gcc_assert (!REG_P (x) || REGNO_QTY_VALID_P (REGNO (x)));
1588e4b17023SJohn Marino
1589e4b17023SJohn Marino /* If X is a hard register, show it is being put in the table. */
1590e4b17023SJohn Marino if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER)
1591e4b17023SJohn Marino add_to_hard_reg_set (&hard_regs_in_table, GET_MODE (x), REGNO (x));
1592e4b17023SJohn Marino
1593e4b17023SJohn Marino /* Put an element for X into the right hash bucket. */
1594e4b17023SJohn Marino
1595e4b17023SJohn Marino elt = free_element_chain;
1596e4b17023SJohn Marino if (elt)
1597e4b17023SJohn Marino free_element_chain = elt->next_same_hash;
1598e4b17023SJohn Marino else
1599e4b17023SJohn Marino elt = XNEW (struct table_elt);
1600e4b17023SJohn Marino
1601e4b17023SJohn Marino elt->exp = x;
1602e4b17023SJohn Marino elt->canon_exp = NULL_RTX;
1603e4b17023SJohn Marino elt->cost = cost;
1604e4b17023SJohn Marino elt->regcost = reg_cost;
1605e4b17023SJohn Marino elt->next_same_value = 0;
1606e4b17023SJohn Marino elt->prev_same_value = 0;
1607e4b17023SJohn Marino elt->next_same_hash = table[hash];
1608e4b17023SJohn Marino elt->prev_same_hash = 0;
1609e4b17023SJohn Marino elt->related_value = 0;
1610e4b17023SJohn Marino elt->in_memory = 0;
1611e4b17023SJohn Marino elt->mode = mode;
1612e4b17023SJohn Marino elt->is_const = (CONSTANT_P (x) || fixed_base_plus_p (x));
1613e4b17023SJohn Marino
1614e4b17023SJohn Marino if (table[hash])
1615e4b17023SJohn Marino table[hash]->prev_same_hash = elt;
1616e4b17023SJohn Marino table[hash] = elt;
1617e4b17023SJohn Marino
1618e4b17023SJohn Marino /* Put it into the proper value-class. */
1619e4b17023SJohn Marino if (classp)
1620e4b17023SJohn Marino {
1621e4b17023SJohn Marino classp = classp->first_same_value;
1622e4b17023SJohn Marino if (CHEAPER (elt, classp))
1623e4b17023SJohn Marino /* Insert at the head of the class. */
1624e4b17023SJohn Marino {
1625e4b17023SJohn Marino struct table_elt *p;
1626e4b17023SJohn Marino elt->next_same_value = classp;
1627e4b17023SJohn Marino classp->prev_same_value = elt;
1628e4b17023SJohn Marino elt->first_same_value = elt;
1629e4b17023SJohn Marino
1630e4b17023SJohn Marino for (p = classp; p; p = p->next_same_value)
1631e4b17023SJohn Marino p->first_same_value = elt;
1632e4b17023SJohn Marino }
1633e4b17023SJohn Marino else
1634e4b17023SJohn Marino {
1635e4b17023SJohn Marino /* Insert not at head of the class. */
1636e4b17023SJohn Marino /* Put it after the last element cheaper than X. */
1637e4b17023SJohn Marino struct table_elt *p, *next;
1638e4b17023SJohn Marino
1639e4b17023SJohn Marino for (p = classp;
1640e4b17023SJohn Marino (next = p->next_same_value) && CHEAPER (next, elt);
1641e4b17023SJohn Marino p = next)
1642e4b17023SJohn Marino ;
1643e4b17023SJohn Marino
1644e4b17023SJohn Marino /* Put it after P and before NEXT. */
1645e4b17023SJohn Marino elt->next_same_value = next;
1646e4b17023SJohn Marino if (next)
1647e4b17023SJohn Marino next->prev_same_value = elt;
1648e4b17023SJohn Marino
1649e4b17023SJohn Marino elt->prev_same_value = p;
1650e4b17023SJohn Marino p->next_same_value = elt;
1651e4b17023SJohn Marino elt->first_same_value = classp;
1652e4b17023SJohn Marino }
1653e4b17023SJohn Marino }
1654e4b17023SJohn Marino else
1655e4b17023SJohn Marino elt->first_same_value = elt;
1656e4b17023SJohn Marino
1657e4b17023SJohn Marino /* If this is a constant being set equivalent to a register or a register
1658e4b17023SJohn Marino being set equivalent to a constant, note the constant equivalence.
1659e4b17023SJohn Marino
1660e4b17023SJohn Marino If this is a constant, it cannot be equivalent to a different constant,
1661e4b17023SJohn Marino and a constant is the only thing that can be cheaper than a register. So
1662e4b17023SJohn Marino we know the register is the head of the class (before the constant was
1663e4b17023SJohn Marino inserted).
1664e4b17023SJohn Marino
1665e4b17023SJohn Marino If this is a register that is not already known equivalent to a
1666e4b17023SJohn Marino constant, we must check the entire class.
1667e4b17023SJohn Marino
1668e4b17023SJohn Marino If this is a register that is already known equivalent to an insn,
1669e4b17023SJohn Marino update the qtys `const_insn' to show that `this_insn' is the latest
1670e4b17023SJohn Marino insn making that quantity equivalent to the constant. */
1671e4b17023SJohn Marino
1672e4b17023SJohn Marino if (elt->is_const && classp && REG_P (classp->exp)
1673e4b17023SJohn Marino && !REG_P (x))
1674e4b17023SJohn Marino {
1675e4b17023SJohn Marino int exp_q = REG_QTY (REGNO (classp->exp));
1676e4b17023SJohn Marino struct qty_table_elem *exp_ent = &qty_table[exp_q];
1677e4b17023SJohn Marino
1678e4b17023SJohn Marino exp_ent->const_rtx = gen_lowpart (exp_ent->mode, x);
1679e4b17023SJohn Marino exp_ent->const_insn = this_insn;
1680e4b17023SJohn Marino }
1681e4b17023SJohn Marino
1682e4b17023SJohn Marino else if (REG_P (x)
1683e4b17023SJohn Marino && classp
1684e4b17023SJohn Marino && ! qty_table[REG_QTY (REGNO (x))].const_rtx
1685e4b17023SJohn Marino && ! elt->is_const)
1686e4b17023SJohn Marino {
1687e4b17023SJohn Marino struct table_elt *p;
1688e4b17023SJohn Marino
1689e4b17023SJohn Marino for (p = classp; p != 0; p = p->next_same_value)
1690e4b17023SJohn Marino {
1691e4b17023SJohn Marino if (p->is_const && !REG_P (p->exp))
1692e4b17023SJohn Marino {
1693e4b17023SJohn Marino int x_q = REG_QTY (REGNO (x));
1694e4b17023SJohn Marino struct qty_table_elem *x_ent = &qty_table[x_q];
1695e4b17023SJohn Marino
1696e4b17023SJohn Marino x_ent->const_rtx
1697e4b17023SJohn Marino = gen_lowpart (GET_MODE (x), p->exp);
1698e4b17023SJohn Marino x_ent->const_insn = this_insn;
1699e4b17023SJohn Marino break;
1700e4b17023SJohn Marino }
1701e4b17023SJohn Marino }
1702e4b17023SJohn Marino }
1703e4b17023SJohn Marino
1704e4b17023SJohn Marino else if (REG_P (x)
1705e4b17023SJohn Marino && qty_table[REG_QTY (REGNO (x))].const_rtx
1706e4b17023SJohn Marino && GET_MODE (x) == qty_table[REG_QTY (REGNO (x))].mode)
1707e4b17023SJohn Marino qty_table[REG_QTY (REGNO (x))].const_insn = this_insn;
1708e4b17023SJohn Marino
1709e4b17023SJohn Marino /* If this is a constant with symbolic value,
1710e4b17023SJohn Marino and it has a term with an explicit integer value,
1711e4b17023SJohn Marino link it up with related expressions. */
1712e4b17023SJohn Marino if (GET_CODE (x) == CONST)
1713e4b17023SJohn Marino {
1714e4b17023SJohn Marino rtx subexp = get_related_value (x);
1715e4b17023SJohn Marino unsigned subhash;
1716e4b17023SJohn Marino struct table_elt *subelt, *subelt_prev;
1717e4b17023SJohn Marino
1718e4b17023SJohn Marino if (subexp != 0)
1719e4b17023SJohn Marino {
1720e4b17023SJohn Marino /* Get the integer-free subexpression in the hash table. */
1721e4b17023SJohn Marino subhash = SAFE_HASH (subexp, mode);
1722e4b17023SJohn Marino subelt = lookup (subexp, subhash, mode);
1723e4b17023SJohn Marino if (subelt == 0)
1724e4b17023SJohn Marino subelt = insert (subexp, NULL, subhash, mode);
1725e4b17023SJohn Marino /* Initialize SUBELT's circular chain if it has none. */
1726e4b17023SJohn Marino if (subelt->related_value == 0)
1727e4b17023SJohn Marino subelt->related_value = subelt;
1728e4b17023SJohn Marino /* Find the element in the circular chain that precedes SUBELT. */
1729e4b17023SJohn Marino subelt_prev = subelt;
1730e4b17023SJohn Marino while (subelt_prev->related_value != subelt)
1731e4b17023SJohn Marino subelt_prev = subelt_prev->related_value;
1732e4b17023SJohn Marino /* Put new ELT into SUBELT's circular chain just before SUBELT.
1733e4b17023SJohn Marino This way the element that follows SUBELT is the oldest one. */
1734e4b17023SJohn Marino elt->related_value = subelt_prev->related_value;
1735e4b17023SJohn Marino subelt_prev->related_value = elt;
1736e4b17023SJohn Marino }
1737e4b17023SJohn Marino }
1738e4b17023SJohn Marino
1739e4b17023SJohn Marino return elt;
1740e4b17023SJohn Marino }
1741e4b17023SJohn Marino
1742e4b17023SJohn Marino /* Wrap insert_with_costs by passing the default costs. */
1743e4b17023SJohn Marino
1744e4b17023SJohn Marino static struct table_elt *
insert(rtx x,struct table_elt * classp,unsigned int hash,enum machine_mode mode)1745e4b17023SJohn Marino insert (rtx x, struct table_elt *classp, unsigned int hash,
1746e4b17023SJohn Marino enum machine_mode mode)
1747e4b17023SJohn Marino {
1748e4b17023SJohn Marino return
1749e4b17023SJohn Marino insert_with_costs (x, classp, hash, mode, COST (x), approx_reg_cost (x));
1750e4b17023SJohn Marino }
1751e4b17023SJohn Marino
1752e4b17023SJohn Marino
1753e4b17023SJohn Marino /* Given two equivalence classes, CLASS1 and CLASS2, put all the entries from
1754e4b17023SJohn Marino CLASS2 into CLASS1. This is done when we have reached an insn which makes
1755e4b17023SJohn Marino the two classes equivalent.
1756e4b17023SJohn Marino
1757e4b17023SJohn Marino CLASS1 will be the surviving class; CLASS2 should not be used after this
1758e4b17023SJohn Marino call.
1759e4b17023SJohn Marino
1760e4b17023SJohn Marino Any invalid entries in CLASS2 will not be copied. */
1761e4b17023SJohn Marino
1762e4b17023SJohn Marino static void
merge_equiv_classes(struct table_elt * class1,struct table_elt * class2)1763e4b17023SJohn Marino merge_equiv_classes (struct table_elt *class1, struct table_elt *class2)
1764e4b17023SJohn Marino {
1765e4b17023SJohn Marino struct table_elt *elt, *next, *new_elt;
1766e4b17023SJohn Marino
1767e4b17023SJohn Marino /* Ensure we start with the head of the classes. */
1768e4b17023SJohn Marino class1 = class1->first_same_value;
1769e4b17023SJohn Marino class2 = class2->first_same_value;
1770e4b17023SJohn Marino
1771e4b17023SJohn Marino /* If they were already equal, forget it. */
1772e4b17023SJohn Marino if (class1 == class2)
1773e4b17023SJohn Marino return;
1774e4b17023SJohn Marino
1775e4b17023SJohn Marino for (elt = class2; elt; elt = next)
1776e4b17023SJohn Marino {
1777e4b17023SJohn Marino unsigned int hash;
1778e4b17023SJohn Marino rtx exp = elt->exp;
1779e4b17023SJohn Marino enum machine_mode mode = elt->mode;
1780e4b17023SJohn Marino
1781e4b17023SJohn Marino next = elt->next_same_value;
1782e4b17023SJohn Marino
1783e4b17023SJohn Marino /* Remove old entry, make a new one in CLASS1's class.
1784e4b17023SJohn Marino Don't do this for invalid entries as we cannot find their
1785e4b17023SJohn Marino hash code (it also isn't necessary). */
1786e4b17023SJohn Marino if (REG_P (exp) || exp_equiv_p (exp, exp, 1, false))
1787e4b17023SJohn Marino {
1788e4b17023SJohn Marino bool need_rehash = false;
1789e4b17023SJohn Marino
1790e4b17023SJohn Marino hash_arg_in_memory = 0;
1791e4b17023SJohn Marino hash = HASH (exp, mode);
1792e4b17023SJohn Marino
1793e4b17023SJohn Marino if (REG_P (exp))
1794e4b17023SJohn Marino {
1795e4b17023SJohn Marino need_rehash = REGNO_QTY_VALID_P (REGNO (exp));
1796e4b17023SJohn Marino delete_reg_equiv (REGNO (exp));
1797e4b17023SJohn Marino }
1798e4b17023SJohn Marino
1799e4b17023SJohn Marino if (REG_P (exp) && REGNO (exp) >= FIRST_PSEUDO_REGISTER)
1800e4b17023SJohn Marino remove_pseudo_from_table (exp, hash);
1801e4b17023SJohn Marino else
1802e4b17023SJohn Marino remove_from_table (elt, hash);
1803e4b17023SJohn Marino
1804e4b17023SJohn Marino if (insert_regs (exp, class1, 0) || need_rehash)
1805e4b17023SJohn Marino {
1806e4b17023SJohn Marino rehash_using_reg (exp);
1807e4b17023SJohn Marino hash = HASH (exp, mode);
1808e4b17023SJohn Marino }
1809e4b17023SJohn Marino new_elt = insert (exp, class1, hash, mode);
1810e4b17023SJohn Marino new_elt->in_memory = hash_arg_in_memory;
1811e4b17023SJohn Marino }
1812e4b17023SJohn Marino }
1813e4b17023SJohn Marino }
1814e4b17023SJohn Marino
1815e4b17023SJohn Marino /* Flush the entire hash table. */
1816e4b17023SJohn Marino
1817e4b17023SJohn Marino static void
flush_hash_table(void)1818e4b17023SJohn Marino flush_hash_table (void)
1819e4b17023SJohn Marino {
1820e4b17023SJohn Marino int i;
1821e4b17023SJohn Marino struct table_elt *p;
1822e4b17023SJohn Marino
1823e4b17023SJohn Marino for (i = 0; i < HASH_SIZE; i++)
1824e4b17023SJohn Marino for (p = table[i]; p; p = table[i])
1825e4b17023SJohn Marino {
1826e4b17023SJohn Marino /* Note that invalidate can remove elements
1827e4b17023SJohn Marino after P in the current hash chain. */
1828e4b17023SJohn Marino if (REG_P (p->exp))
1829e4b17023SJohn Marino invalidate (p->exp, VOIDmode);
1830e4b17023SJohn Marino else
1831e4b17023SJohn Marino remove_from_table (p, i);
1832e4b17023SJohn Marino }
1833e4b17023SJohn Marino }
1834e4b17023SJohn Marino
1835e4b17023SJohn Marino /* Function called for each rtx to check whether true dependence exist. */
1836e4b17023SJohn Marino struct check_dependence_data
1837e4b17023SJohn Marino {
1838e4b17023SJohn Marino enum machine_mode mode;
1839e4b17023SJohn Marino rtx exp;
1840e4b17023SJohn Marino rtx addr;
1841e4b17023SJohn Marino };
1842e4b17023SJohn Marino
1843e4b17023SJohn Marino static int
check_dependence(rtx * x,void * data)1844e4b17023SJohn Marino check_dependence (rtx *x, void *data)
1845e4b17023SJohn Marino {
1846e4b17023SJohn Marino struct check_dependence_data *d = (struct check_dependence_data *) data;
1847e4b17023SJohn Marino if (*x && MEM_P (*x))
1848e4b17023SJohn Marino return canon_true_dependence (d->exp, d->mode, d->addr, *x, NULL_RTX);
1849e4b17023SJohn Marino else
1850e4b17023SJohn Marino return 0;
1851e4b17023SJohn Marino }
1852e4b17023SJohn Marino
1853e4b17023SJohn Marino /* Remove from the hash table, or mark as invalid, all expressions whose
1854e4b17023SJohn Marino values could be altered by storing in X. X is a register, a subreg, or
1855e4b17023SJohn Marino a memory reference with nonvarying address (because, when a memory
1856e4b17023SJohn Marino reference with a varying address is stored in, all memory references are
1857e4b17023SJohn Marino removed by invalidate_memory so specific invalidation is superfluous).
1858e4b17023SJohn Marino FULL_MODE, if not VOIDmode, indicates that this much should be
1859e4b17023SJohn Marino invalidated instead of just the amount indicated by the mode of X. This
1860e4b17023SJohn Marino is only used for bitfield stores into memory.
1861e4b17023SJohn Marino
1862e4b17023SJohn Marino A nonvarying address may be just a register or just a symbol reference,
1863e4b17023SJohn Marino or it may be either of those plus a numeric offset. */
1864e4b17023SJohn Marino
1865e4b17023SJohn Marino static void
invalidate(rtx x,enum machine_mode full_mode)1866e4b17023SJohn Marino invalidate (rtx x, enum machine_mode full_mode)
1867e4b17023SJohn Marino {
1868e4b17023SJohn Marino int i;
1869e4b17023SJohn Marino struct table_elt *p;
1870e4b17023SJohn Marino rtx addr;
1871e4b17023SJohn Marino
1872e4b17023SJohn Marino switch (GET_CODE (x))
1873e4b17023SJohn Marino {
1874e4b17023SJohn Marino case REG:
1875e4b17023SJohn Marino {
1876e4b17023SJohn Marino /* If X is a register, dependencies on its contents are recorded
1877e4b17023SJohn Marino through the qty number mechanism. Just change the qty number of
1878e4b17023SJohn Marino the register, mark it as invalid for expressions that refer to it,
1879e4b17023SJohn Marino and remove it itself. */
1880e4b17023SJohn Marino unsigned int regno = REGNO (x);
1881e4b17023SJohn Marino unsigned int hash = HASH (x, GET_MODE (x));
1882e4b17023SJohn Marino
1883e4b17023SJohn Marino /* Remove REGNO from any quantity list it might be on and indicate
1884e4b17023SJohn Marino that its value might have changed. If it is a pseudo, remove its
1885e4b17023SJohn Marino entry from the hash table.
1886e4b17023SJohn Marino
1887e4b17023SJohn Marino For a hard register, we do the first two actions above for any
1888e4b17023SJohn Marino additional hard registers corresponding to X. Then, if any of these
1889e4b17023SJohn Marino registers are in the table, we must remove any REG entries that
1890e4b17023SJohn Marino overlap these registers. */
1891e4b17023SJohn Marino
1892e4b17023SJohn Marino delete_reg_equiv (regno);
1893e4b17023SJohn Marino REG_TICK (regno)++;
1894e4b17023SJohn Marino SUBREG_TICKED (regno) = -1;
1895e4b17023SJohn Marino
1896e4b17023SJohn Marino if (regno >= FIRST_PSEUDO_REGISTER)
1897e4b17023SJohn Marino remove_pseudo_from_table (x, hash);
1898e4b17023SJohn Marino else
1899e4b17023SJohn Marino {
1900e4b17023SJohn Marino HOST_WIDE_INT in_table
1901e4b17023SJohn Marino = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
1902e4b17023SJohn Marino unsigned int endregno = END_HARD_REGNO (x);
1903e4b17023SJohn Marino unsigned int tregno, tendregno, rn;
1904e4b17023SJohn Marino struct table_elt *p, *next;
1905e4b17023SJohn Marino
1906e4b17023SJohn Marino CLEAR_HARD_REG_BIT (hard_regs_in_table, regno);
1907e4b17023SJohn Marino
1908e4b17023SJohn Marino for (rn = regno + 1; rn < endregno; rn++)
1909e4b17023SJohn Marino {
1910e4b17023SJohn Marino in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, rn);
1911e4b17023SJohn Marino CLEAR_HARD_REG_BIT (hard_regs_in_table, rn);
1912e4b17023SJohn Marino delete_reg_equiv (rn);
1913e4b17023SJohn Marino REG_TICK (rn)++;
1914e4b17023SJohn Marino SUBREG_TICKED (rn) = -1;
1915e4b17023SJohn Marino }
1916e4b17023SJohn Marino
1917e4b17023SJohn Marino if (in_table)
1918e4b17023SJohn Marino for (hash = 0; hash < HASH_SIZE; hash++)
1919e4b17023SJohn Marino for (p = table[hash]; p; p = next)
1920e4b17023SJohn Marino {
1921e4b17023SJohn Marino next = p->next_same_hash;
1922e4b17023SJohn Marino
1923e4b17023SJohn Marino if (!REG_P (p->exp)
1924e4b17023SJohn Marino || REGNO (p->exp) >= FIRST_PSEUDO_REGISTER)
1925e4b17023SJohn Marino continue;
1926e4b17023SJohn Marino
1927e4b17023SJohn Marino tregno = REGNO (p->exp);
1928e4b17023SJohn Marino tendregno = END_HARD_REGNO (p->exp);
1929e4b17023SJohn Marino if (tendregno > regno && tregno < endregno)
1930e4b17023SJohn Marino remove_from_table (p, hash);
1931e4b17023SJohn Marino }
1932e4b17023SJohn Marino }
1933e4b17023SJohn Marino }
1934e4b17023SJohn Marino return;
1935e4b17023SJohn Marino
1936e4b17023SJohn Marino case SUBREG:
1937e4b17023SJohn Marino invalidate (SUBREG_REG (x), VOIDmode);
1938e4b17023SJohn Marino return;
1939e4b17023SJohn Marino
1940e4b17023SJohn Marino case PARALLEL:
1941e4b17023SJohn Marino for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
1942e4b17023SJohn Marino invalidate (XVECEXP (x, 0, i), VOIDmode);
1943e4b17023SJohn Marino return;
1944e4b17023SJohn Marino
1945e4b17023SJohn Marino case EXPR_LIST:
1946e4b17023SJohn Marino /* This is part of a disjoint return value; extract the location in
1947e4b17023SJohn Marino question ignoring the offset. */
1948e4b17023SJohn Marino invalidate (XEXP (x, 0), VOIDmode);
1949e4b17023SJohn Marino return;
1950e4b17023SJohn Marino
1951e4b17023SJohn Marino case MEM:
1952e4b17023SJohn Marino addr = canon_rtx (get_addr (XEXP (x, 0)));
1953e4b17023SJohn Marino /* Calculate the canonical version of X here so that
1954e4b17023SJohn Marino true_dependence doesn't generate new RTL for X on each call. */
1955e4b17023SJohn Marino x = canon_rtx (x);
1956e4b17023SJohn Marino
1957e4b17023SJohn Marino /* Remove all hash table elements that refer to overlapping pieces of
1958e4b17023SJohn Marino memory. */
1959e4b17023SJohn Marino if (full_mode == VOIDmode)
1960e4b17023SJohn Marino full_mode = GET_MODE (x);
1961e4b17023SJohn Marino
1962e4b17023SJohn Marino for (i = 0; i < HASH_SIZE; i++)
1963e4b17023SJohn Marino {
1964e4b17023SJohn Marino struct table_elt *next;
1965e4b17023SJohn Marino
1966e4b17023SJohn Marino for (p = table[i]; p; p = next)
1967e4b17023SJohn Marino {
1968e4b17023SJohn Marino next = p->next_same_hash;
1969e4b17023SJohn Marino if (p->in_memory)
1970e4b17023SJohn Marino {
1971e4b17023SJohn Marino struct check_dependence_data d;
1972e4b17023SJohn Marino
1973e4b17023SJohn Marino /* Just canonicalize the expression once;
1974e4b17023SJohn Marino otherwise each time we call invalidate
1975e4b17023SJohn Marino true_dependence will canonicalize the
1976e4b17023SJohn Marino expression again. */
1977e4b17023SJohn Marino if (!p->canon_exp)
1978e4b17023SJohn Marino p->canon_exp = canon_rtx (p->exp);
1979e4b17023SJohn Marino d.exp = x;
1980e4b17023SJohn Marino d.addr = addr;
1981e4b17023SJohn Marino d.mode = full_mode;
1982e4b17023SJohn Marino if (for_each_rtx (&p->canon_exp, check_dependence, &d))
1983e4b17023SJohn Marino remove_from_table (p, i);
1984e4b17023SJohn Marino }
1985e4b17023SJohn Marino }
1986e4b17023SJohn Marino }
1987e4b17023SJohn Marino return;
1988e4b17023SJohn Marino
1989e4b17023SJohn Marino default:
1990e4b17023SJohn Marino gcc_unreachable ();
1991e4b17023SJohn Marino }
1992e4b17023SJohn Marino }
1993e4b17023SJohn Marino
1994e4b17023SJohn Marino /* Remove all expressions that refer to register REGNO,
1995e4b17023SJohn Marino since they are already invalid, and we are about to
1996e4b17023SJohn Marino mark that register valid again and don't want the old
1997e4b17023SJohn Marino expressions to reappear as valid. */
1998e4b17023SJohn Marino
1999e4b17023SJohn Marino static void
remove_invalid_refs(unsigned int regno)2000e4b17023SJohn Marino remove_invalid_refs (unsigned int regno)
2001e4b17023SJohn Marino {
2002e4b17023SJohn Marino unsigned int i;
2003e4b17023SJohn Marino struct table_elt *p, *next;
2004e4b17023SJohn Marino
2005e4b17023SJohn Marino for (i = 0; i < HASH_SIZE; i++)
2006e4b17023SJohn Marino for (p = table[i]; p; p = next)
2007e4b17023SJohn Marino {
2008e4b17023SJohn Marino next = p->next_same_hash;
2009e4b17023SJohn Marino if (!REG_P (p->exp)
2010e4b17023SJohn Marino && refers_to_regno_p (regno, regno + 1, p->exp, (rtx *) 0))
2011e4b17023SJohn Marino remove_from_table (p, i);
2012e4b17023SJohn Marino }
2013e4b17023SJohn Marino }
2014e4b17023SJohn Marino
2015e4b17023SJohn Marino /* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
2016e4b17023SJohn Marino and mode MODE. */
2017e4b17023SJohn Marino static void
remove_invalid_subreg_refs(unsigned int regno,unsigned int offset,enum machine_mode mode)2018e4b17023SJohn Marino remove_invalid_subreg_refs (unsigned int regno, unsigned int offset,
2019e4b17023SJohn Marino enum machine_mode mode)
2020e4b17023SJohn Marino {
2021e4b17023SJohn Marino unsigned int i;
2022e4b17023SJohn Marino struct table_elt *p, *next;
2023e4b17023SJohn Marino unsigned int end = offset + (GET_MODE_SIZE (mode) - 1);
2024e4b17023SJohn Marino
2025e4b17023SJohn Marino for (i = 0; i < HASH_SIZE; i++)
2026e4b17023SJohn Marino for (p = table[i]; p; p = next)
2027e4b17023SJohn Marino {
2028e4b17023SJohn Marino rtx exp = p->exp;
2029e4b17023SJohn Marino next = p->next_same_hash;
2030e4b17023SJohn Marino
2031e4b17023SJohn Marino if (!REG_P (exp)
2032e4b17023SJohn Marino && (GET_CODE (exp) != SUBREG
2033e4b17023SJohn Marino || !REG_P (SUBREG_REG (exp))
2034e4b17023SJohn Marino || REGNO (SUBREG_REG (exp)) != regno
2035e4b17023SJohn Marino || (((SUBREG_BYTE (exp)
2036e4b17023SJohn Marino + (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
2037e4b17023SJohn Marino && SUBREG_BYTE (exp) <= end))
2038e4b17023SJohn Marino && refers_to_regno_p (regno, regno + 1, p->exp, (rtx *) 0))
2039e4b17023SJohn Marino remove_from_table (p, i);
2040e4b17023SJohn Marino }
2041e4b17023SJohn Marino }
2042e4b17023SJohn Marino
2043e4b17023SJohn Marino /* Recompute the hash codes of any valid entries in the hash table that
2044e4b17023SJohn Marino reference X, if X is a register, or SUBREG_REG (X) if X is a SUBREG.
2045e4b17023SJohn Marino
2046e4b17023SJohn Marino This is called when we make a jump equivalence. */
2047e4b17023SJohn Marino
2048e4b17023SJohn Marino static void
rehash_using_reg(rtx x)2049e4b17023SJohn Marino rehash_using_reg (rtx x)
2050e4b17023SJohn Marino {
2051e4b17023SJohn Marino unsigned int i;
2052e4b17023SJohn Marino struct table_elt *p, *next;
2053e4b17023SJohn Marino unsigned hash;
2054e4b17023SJohn Marino
2055e4b17023SJohn Marino if (GET_CODE (x) == SUBREG)
2056e4b17023SJohn Marino x = SUBREG_REG (x);
2057e4b17023SJohn Marino
2058e4b17023SJohn Marino /* If X is not a register or if the register is known not to be in any
2059e4b17023SJohn Marino valid entries in the table, we have no work to do. */
2060e4b17023SJohn Marino
2061e4b17023SJohn Marino if (!REG_P (x)
2062e4b17023SJohn Marino || REG_IN_TABLE (REGNO (x)) < 0
2063e4b17023SJohn Marino || REG_IN_TABLE (REGNO (x)) != REG_TICK (REGNO (x)))
2064e4b17023SJohn Marino return;
2065e4b17023SJohn Marino
2066e4b17023SJohn Marino /* Scan all hash chains looking for valid entries that mention X.
2067e4b17023SJohn Marino If we find one and it is in the wrong hash chain, move it. */
2068e4b17023SJohn Marino
2069e4b17023SJohn Marino for (i = 0; i < HASH_SIZE; i++)
2070e4b17023SJohn Marino for (p = table[i]; p; p = next)
2071e4b17023SJohn Marino {
2072e4b17023SJohn Marino next = p->next_same_hash;
2073e4b17023SJohn Marino if (reg_mentioned_p (x, p->exp)
2074e4b17023SJohn Marino && exp_equiv_p (p->exp, p->exp, 1, false)
2075e4b17023SJohn Marino && i != (hash = SAFE_HASH (p->exp, p->mode)))
2076e4b17023SJohn Marino {
2077e4b17023SJohn Marino if (p->next_same_hash)
2078e4b17023SJohn Marino p->next_same_hash->prev_same_hash = p->prev_same_hash;
2079e4b17023SJohn Marino
2080e4b17023SJohn Marino if (p->prev_same_hash)
2081e4b17023SJohn Marino p->prev_same_hash->next_same_hash = p->next_same_hash;
2082e4b17023SJohn Marino else
2083e4b17023SJohn Marino table[i] = p->next_same_hash;
2084e4b17023SJohn Marino
2085e4b17023SJohn Marino p->next_same_hash = table[hash];
2086e4b17023SJohn Marino p->prev_same_hash = 0;
2087e4b17023SJohn Marino if (table[hash])
2088e4b17023SJohn Marino table[hash]->prev_same_hash = p;
2089e4b17023SJohn Marino table[hash] = p;
2090e4b17023SJohn Marino }
2091e4b17023SJohn Marino }
2092e4b17023SJohn Marino }
2093e4b17023SJohn Marino
2094e4b17023SJohn Marino /* Remove from the hash table any expression that is a call-clobbered
2095e4b17023SJohn Marino register. Also update their TICK values. */
2096e4b17023SJohn Marino
2097e4b17023SJohn Marino static void
invalidate_for_call(void)2098e4b17023SJohn Marino invalidate_for_call (void)
2099e4b17023SJohn Marino {
2100e4b17023SJohn Marino unsigned int regno, endregno;
2101e4b17023SJohn Marino unsigned int i;
2102e4b17023SJohn Marino unsigned hash;
2103e4b17023SJohn Marino struct table_elt *p, *next;
2104e4b17023SJohn Marino int in_table = 0;
2105e4b17023SJohn Marino
2106e4b17023SJohn Marino /* Go through all the hard registers. For each that is clobbered in
2107e4b17023SJohn Marino a CALL_INSN, remove the register from quantity chains and update
2108e4b17023SJohn Marino reg_tick if defined. Also see if any of these registers is currently
2109e4b17023SJohn Marino in the table. */
2110e4b17023SJohn Marino
2111e4b17023SJohn Marino for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
2112e4b17023SJohn Marino if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
2113e4b17023SJohn Marino {
2114e4b17023SJohn Marino delete_reg_equiv (regno);
2115e4b17023SJohn Marino if (REG_TICK (regno) >= 0)
2116e4b17023SJohn Marino {
2117e4b17023SJohn Marino REG_TICK (regno)++;
2118e4b17023SJohn Marino SUBREG_TICKED (regno) = -1;
2119e4b17023SJohn Marino }
2120e4b17023SJohn Marino
2121e4b17023SJohn Marino in_table |= (TEST_HARD_REG_BIT (hard_regs_in_table, regno) != 0);
2122e4b17023SJohn Marino }
2123e4b17023SJohn Marino
2124e4b17023SJohn Marino /* In the case where we have no call-clobbered hard registers in the
2125e4b17023SJohn Marino table, we are done. Otherwise, scan the table and remove any
2126e4b17023SJohn Marino entry that overlaps a call-clobbered register. */
2127e4b17023SJohn Marino
2128e4b17023SJohn Marino if (in_table)
2129e4b17023SJohn Marino for (hash = 0; hash < HASH_SIZE; hash++)
2130e4b17023SJohn Marino for (p = table[hash]; p; p = next)
2131e4b17023SJohn Marino {
2132e4b17023SJohn Marino next = p->next_same_hash;
2133e4b17023SJohn Marino
2134e4b17023SJohn Marino if (!REG_P (p->exp)
2135e4b17023SJohn Marino || REGNO (p->exp) >= FIRST_PSEUDO_REGISTER)
2136e4b17023SJohn Marino continue;
2137e4b17023SJohn Marino
2138e4b17023SJohn Marino regno = REGNO (p->exp);
2139e4b17023SJohn Marino endregno = END_HARD_REGNO (p->exp);
2140e4b17023SJohn Marino
2141e4b17023SJohn Marino for (i = regno; i < endregno; i++)
2142e4b17023SJohn Marino if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
2143e4b17023SJohn Marino {
2144e4b17023SJohn Marino remove_from_table (p, hash);
2145e4b17023SJohn Marino break;
2146e4b17023SJohn Marino }
2147e4b17023SJohn Marino }
2148e4b17023SJohn Marino }
2149e4b17023SJohn Marino
2150e4b17023SJohn Marino /* Given an expression X of type CONST,
2151e4b17023SJohn Marino and ELT which is its table entry (or 0 if it
2152e4b17023SJohn Marino is not in the hash table),
2153e4b17023SJohn Marino return an alternate expression for X as a register plus integer.
2154e4b17023SJohn Marino If none can be found, return 0. */
2155e4b17023SJohn Marino
2156e4b17023SJohn Marino static rtx
use_related_value(rtx x,struct table_elt * elt)2157e4b17023SJohn Marino use_related_value (rtx x, struct table_elt *elt)
2158e4b17023SJohn Marino {
2159e4b17023SJohn Marino struct table_elt *relt = 0;
2160e4b17023SJohn Marino struct table_elt *p, *q;
2161e4b17023SJohn Marino HOST_WIDE_INT offset;
2162e4b17023SJohn Marino
2163e4b17023SJohn Marino /* First, is there anything related known?
2164e4b17023SJohn Marino If we have a table element, we can tell from that.
2165e4b17023SJohn Marino Otherwise, must look it up. */
2166e4b17023SJohn Marino
2167e4b17023SJohn Marino if (elt != 0 && elt->related_value != 0)
2168e4b17023SJohn Marino relt = elt;
2169e4b17023SJohn Marino else if (elt == 0 && GET_CODE (x) == CONST)
2170e4b17023SJohn Marino {
2171e4b17023SJohn Marino rtx subexp = get_related_value (x);
2172e4b17023SJohn Marino if (subexp != 0)
2173e4b17023SJohn Marino relt = lookup (subexp,
2174e4b17023SJohn Marino SAFE_HASH (subexp, GET_MODE (subexp)),
2175e4b17023SJohn Marino GET_MODE (subexp));
2176e4b17023SJohn Marino }
2177e4b17023SJohn Marino
2178e4b17023SJohn Marino if (relt == 0)
2179e4b17023SJohn Marino return 0;
2180e4b17023SJohn Marino
2181e4b17023SJohn Marino /* Search all related table entries for one that has an
2182e4b17023SJohn Marino equivalent register. */
2183e4b17023SJohn Marino
2184e4b17023SJohn Marino p = relt;
2185e4b17023SJohn Marino while (1)
2186e4b17023SJohn Marino {
2187e4b17023SJohn Marino /* This loop is strange in that it is executed in two different cases.
2188e4b17023SJohn Marino The first is when X is already in the table. Then it is searching
2189e4b17023SJohn Marino the RELATED_VALUE list of X's class (RELT). The second case is when
2190e4b17023SJohn Marino X is not in the table. Then RELT points to a class for the related
2191e4b17023SJohn Marino value.
2192e4b17023SJohn Marino
2193e4b17023SJohn Marino Ensure that, whatever case we are in, that we ignore classes that have
2194e4b17023SJohn Marino the same value as X. */
2195e4b17023SJohn Marino
2196e4b17023SJohn Marino if (rtx_equal_p (x, p->exp))
2197e4b17023SJohn Marino q = 0;
2198e4b17023SJohn Marino else
2199e4b17023SJohn Marino for (q = p->first_same_value; q; q = q->next_same_value)
2200e4b17023SJohn Marino if (REG_P (q->exp))
2201e4b17023SJohn Marino break;
2202e4b17023SJohn Marino
2203e4b17023SJohn Marino if (q)
2204e4b17023SJohn Marino break;
2205e4b17023SJohn Marino
2206e4b17023SJohn Marino p = p->related_value;
2207e4b17023SJohn Marino
2208e4b17023SJohn Marino /* We went all the way around, so there is nothing to be found.
2209e4b17023SJohn Marino Alternatively, perhaps RELT was in the table for some other reason
2210e4b17023SJohn Marino and it has no related values recorded. */
2211e4b17023SJohn Marino if (p == relt || p == 0)
2212e4b17023SJohn Marino break;
2213e4b17023SJohn Marino }
2214e4b17023SJohn Marino
2215e4b17023SJohn Marino if (q == 0)
2216e4b17023SJohn Marino return 0;
2217e4b17023SJohn Marino
2218e4b17023SJohn Marino offset = (get_integer_term (x) - get_integer_term (p->exp));
2219e4b17023SJohn Marino /* Note: OFFSET may be 0 if P->xexp and X are related by commutativity. */
2220e4b17023SJohn Marino return plus_constant (q->exp, offset);
2221e4b17023SJohn Marino }
2222e4b17023SJohn Marino
2223e4b17023SJohn Marino
2224e4b17023SJohn Marino /* Hash a string. Just add its bytes up. */
2225e4b17023SJohn Marino static inline unsigned
hash_rtx_string(const char * ps)2226e4b17023SJohn Marino hash_rtx_string (const char *ps)
2227e4b17023SJohn Marino {
2228e4b17023SJohn Marino unsigned hash = 0;
2229e4b17023SJohn Marino const unsigned char *p = (const unsigned char *) ps;
2230e4b17023SJohn Marino
2231e4b17023SJohn Marino if (p)
2232e4b17023SJohn Marino while (*p)
2233e4b17023SJohn Marino hash += *p++;
2234e4b17023SJohn Marino
2235e4b17023SJohn Marino return hash;
2236e4b17023SJohn Marino }
2237e4b17023SJohn Marino
2238e4b17023SJohn Marino /* Same as hash_rtx, but call CB on each rtx if it is not NULL.
2239e4b17023SJohn Marino When the callback returns true, we continue with the new rtx. */
2240e4b17023SJohn Marino
2241e4b17023SJohn Marino unsigned
hash_rtx_cb(const_rtx x,enum machine_mode mode,int * do_not_record_p,int * hash_arg_in_memory_p,bool have_reg_qty,hash_rtx_callback_function cb)2242e4b17023SJohn Marino hash_rtx_cb (const_rtx x, enum machine_mode mode,
2243e4b17023SJohn Marino int *do_not_record_p, int *hash_arg_in_memory_p,
2244e4b17023SJohn Marino bool have_reg_qty, hash_rtx_callback_function cb)
2245e4b17023SJohn Marino {
2246e4b17023SJohn Marino int i, j;
2247e4b17023SJohn Marino unsigned hash = 0;
2248e4b17023SJohn Marino enum rtx_code code;
2249e4b17023SJohn Marino const char *fmt;
2250e4b17023SJohn Marino enum machine_mode newmode;
2251e4b17023SJohn Marino rtx newx;
2252e4b17023SJohn Marino
2253e4b17023SJohn Marino /* Used to turn recursion into iteration. We can't rely on GCC's
2254e4b17023SJohn Marino tail-recursion elimination since we need to keep accumulating values
2255e4b17023SJohn Marino in HASH. */
2256e4b17023SJohn Marino repeat:
2257e4b17023SJohn Marino if (x == 0)
2258e4b17023SJohn Marino return hash;
2259e4b17023SJohn Marino
2260e4b17023SJohn Marino /* Invoke the callback first. */
2261e4b17023SJohn Marino if (cb != NULL
2262e4b17023SJohn Marino && ((*cb) (x, mode, &newx, &newmode)))
2263e4b17023SJohn Marino {
2264e4b17023SJohn Marino hash += hash_rtx_cb (newx, newmode, do_not_record_p,
2265e4b17023SJohn Marino hash_arg_in_memory_p, have_reg_qty, cb);
2266e4b17023SJohn Marino return hash;
2267e4b17023SJohn Marino }
2268e4b17023SJohn Marino
2269e4b17023SJohn Marino code = GET_CODE (x);
2270e4b17023SJohn Marino switch (code)
2271e4b17023SJohn Marino {
2272e4b17023SJohn Marino case REG:
2273e4b17023SJohn Marino {
2274e4b17023SJohn Marino unsigned int regno = REGNO (x);
2275e4b17023SJohn Marino
2276e4b17023SJohn Marino if (do_not_record_p && !reload_completed)
2277e4b17023SJohn Marino {
2278e4b17023SJohn Marino /* On some machines, we can't record any non-fixed hard register,
2279e4b17023SJohn Marino because extending its life will cause reload problems. We
2280e4b17023SJohn Marino consider ap, fp, sp, gp to be fixed for this purpose.
2281e4b17023SJohn Marino
2282e4b17023SJohn Marino We also consider CCmode registers to be fixed for this purpose;
2283e4b17023SJohn Marino failure to do so leads to failure to simplify 0<100 type of
2284e4b17023SJohn Marino conditionals.
2285e4b17023SJohn Marino
2286e4b17023SJohn Marino On all machines, we can't record any global registers.
2287e4b17023SJohn Marino Nor should we record any register that is in a small
2288e4b17023SJohn Marino class, as defined by TARGET_CLASS_LIKELY_SPILLED_P. */
2289e4b17023SJohn Marino bool record;
2290e4b17023SJohn Marino
2291e4b17023SJohn Marino if (regno >= FIRST_PSEUDO_REGISTER)
2292e4b17023SJohn Marino record = true;
2293e4b17023SJohn Marino else if (x == frame_pointer_rtx
2294e4b17023SJohn Marino || x == hard_frame_pointer_rtx
2295e4b17023SJohn Marino || x == arg_pointer_rtx
2296e4b17023SJohn Marino || x == stack_pointer_rtx
2297e4b17023SJohn Marino || x == pic_offset_table_rtx)
2298e4b17023SJohn Marino record = true;
2299e4b17023SJohn Marino else if (global_regs[regno])
2300e4b17023SJohn Marino record = false;
2301e4b17023SJohn Marino else if (fixed_regs[regno])
2302e4b17023SJohn Marino record = true;
2303e4b17023SJohn Marino else if (GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
2304e4b17023SJohn Marino record = true;
2305e4b17023SJohn Marino else if (targetm.small_register_classes_for_mode_p (GET_MODE (x)))
2306e4b17023SJohn Marino record = false;
2307e4b17023SJohn Marino else if (targetm.class_likely_spilled_p (REGNO_REG_CLASS (regno)))
2308e4b17023SJohn Marino record = false;
2309e4b17023SJohn Marino else
2310e4b17023SJohn Marino record = true;
2311e4b17023SJohn Marino
2312e4b17023SJohn Marino if (!record)
2313e4b17023SJohn Marino {
2314e4b17023SJohn Marino *do_not_record_p = 1;
2315e4b17023SJohn Marino return 0;
2316e4b17023SJohn Marino }
2317e4b17023SJohn Marino }
2318e4b17023SJohn Marino
2319e4b17023SJohn Marino hash += ((unsigned int) REG << 7);
2320e4b17023SJohn Marino hash += (have_reg_qty ? (unsigned) REG_QTY (regno) : regno);
2321e4b17023SJohn Marino return hash;
2322e4b17023SJohn Marino }
2323e4b17023SJohn Marino
2324e4b17023SJohn Marino /* We handle SUBREG of a REG specially because the underlying
2325e4b17023SJohn Marino reg changes its hash value with every value change; we don't
2326e4b17023SJohn Marino want to have to forget unrelated subregs when one subreg changes. */
2327e4b17023SJohn Marino case SUBREG:
2328e4b17023SJohn Marino {
2329e4b17023SJohn Marino if (REG_P (SUBREG_REG (x)))
2330e4b17023SJohn Marino {
2331e4b17023SJohn Marino hash += (((unsigned int) SUBREG << 7)
2332e4b17023SJohn Marino + REGNO (SUBREG_REG (x))
2333e4b17023SJohn Marino + (SUBREG_BYTE (x) / UNITS_PER_WORD));
2334e4b17023SJohn Marino return hash;
2335e4b17023SJohn Marino }
2336e4b17023SJohn Marino break;
2337e4b17023SJohn Marino }
2338e4b17023SJohn Marino
2339e4b17023SJohn Marino case CONST_INT:
2340e4b17023SJohn Marino hash += (((unsigned int) CONST_INT << 7) + (unsigned int) mode
2341e4b17023SJohn Marino + (unsigned int) INTVAL (x));
2342e4b17023SJohn Marino return hash;
2343e4b17023SJohn Marino
2344e4b17023SJohn Marino case CONST_DOUBLE:
2345e4b17023SJohn Marino /* This is like the general case, except that it only counts
2346e4b17023SJohn Marino the integers representing the constant. */
2347e4b17023SJohn Marino hash += (unsigned int) code + (unsigned int) GET_MODE (x);
2348e4b17023SJohn Marino if (GET_MODE (x) != VOIDmode)
2349e4b17023SJohn Marino hash += real_hash (CONST_DOUBLE_REAL_VALUE (x));
2350e4b17023SJohn Marino else
2351e4b17023SJohn Marino hash += ((unsigned int) CONST_DOUBLE_LOW (x)
2352e4b17023SJohn Marino + (unsigned int) CONST_DOUBLE_HIGH (x));
2353e4b17023SJohn Marino return hash;
2354e4b17023SJohn Marino
2355e4b17023SJohn Marino case CONST_FIXED:
2356e4b17023SJohn Marino hash += (unsigned int) code + (unsigned int) GET_MODE (x);
2357e4b17023SJohn Marino hash += fixed_hash (CONST_FIXED_VALUE (x));
2358e4b17023SJohn Marino return hash;
2359e4b17023SJohn Marino
2360e4b17023SJohn Marino case CONST_VECTOR:
2361e4b17023SJohn Marino {
2362e4b17023SJohn Marino int units;
2363e4b17023SJohn Marino rtx elt;
2364e4b17023SJohn Marino
2365e4b17023SJohn Marino units = CONST_VECTOR_NUNITS (x);
2366e4b17023SJohn Marino
2367e4b17023SJohn Marino for (i = 0; i < units; ++i)
2368e4b17023SJohn Marino {
2369e4b17023SJohn Marino elt = CONST_VECTOR_ELT (x, i);
2370e4b17023SJohn Marino hash += hash_rtx_cb (elt, GET_MODE (elt),
2371e4b17023SJohn Marino do_not_record_p, hash_arg_in_memory_p,
2372e4b17023SJohn Marino have_reg_qty, cb);
2373e4b17023SJohn Marino }
2374e4b17023SJohn Marino
2375e4b17023SJohn Marino return hash;
2376e4b17023SJohn Marino }
2377e4b17023SJohn Marino
2378e4b17023SJohn Marino /* Assume there is only one rtx object for any given label. */
2379e4b17023SJohn Marino case LABEL_REF:
2380e4b17023SJohn Marino /* We don't hash on the address of the CODE_LABEL to avoid bootstrap
2381e4b17023SJohn Marino differences and differences between each stage's debugging dumps. */
2382e4b17023SJohn Marino hash += (((unsigned int) LABEL_REF << 7)
2383e4b17023SJohn Marino + CODE_LABEL_NUMBER (XEXP (x, 0)));
2384e4b17023SJohn Marino return hash;
2385e4b17023SJohn Marino
2386e4b17023SJohn Marino case SYMBOL_REF:
2387e4b17023SJohn Marino {
2388e4b17023SJohn Marino /* Don't hash on the symbol's address to avoid bootstrap differences.
2389e4b17023SJohn Marino Different hash values may cause expressions to be recorded in
2390e4b17023SJohn Marino different orders and thus different registers to be used in the
2391e4b17023SJohn Marino final assembler. This also avoids differences in the dump files
2392e4b17023SJohn Marino between various stages. */
2393e4b17023SJohn Marino unsigned int h = 0;
2394e4b17023SJohn Marino const unsigned char *p = (const unsigned char *) XSTR (x, 0);
2395e4b17023SJohn Marino
2396e4b17023SJohn Marino while (*p)
2397e4b17023SJohn Marino h += (h << 7) + *p++; /* ??? revisit */
2398e4b17023SJohn Marino
2399e4b17023SJohn Marino hash += ((unsigned int) SYMBOL_REF << 7) + h;
2400e4b17023SJohn Marino return hash;
2401e4b17023SJohn Marino }
2402e4b17023SJohn Marino
2403e4b17023SJohn Marino case MEM:
2404e4b17023SJohn Marino /* We don't record if marked volatile or if BLKmode since we don't
2405e4b17023SJohn Marino know the size of the move. */
2406e4b17023SJohn Marino if (do_not_record_p && (MEM_VOLATILE_P (x) || GET_MODE (x) == BLKmode))
2407e4b17023SJohn Marino {
2408e4b17023SJohn Marino *do_not_record_p = 1;
2409e4b17023SJohn Marino return 0;
2410e4b17023SJohn Marino }
2411e4b17023SJohn Marino if (hash_arg_in_memory_p && !MEM_READONLY_P (x))
2412e4b17023SJohn Marino *hash_arg_in_memory_p = 1;
2413e4b17023SJohn Marino
2414e4b17023SJohn Marino /* Now that we have already found this special case,
2415e4b17023SJohn Marino might as well speed it up as much as possible. */
2416e4b17023SJohn Marino hash += (unsigned) MEM;
2417e4b17023SJohn Marino x = XEXP (x, 0);
2418e4b17023SJohn Marino goto repeat;
2419e4b17023SJohn Marino
2420e4b17023SJohn Marino case USE:
2421e4b17023SJohn Marino /* A USE that mentions non-volatile memory needs special
2422e4b17023SJohn Marino handling since the MEM may be BLKmode which normally
2423e4b17023SJohn Marino prevents an entry from being made. Pure calls are
2424e4b17023SJohn Marino marked by a USE which mentions BLKmode memory.
2425e4b17023SJohn Marino See calls.c:emit_call_1. */
2426e4b17023SJohn Marino if (MEM_P (XEXP (x, 0))
2427e4b17023SJohn Marino && ! MEM_VOLATILE_P (XEXP (x, 0)))
2428e4b17023SJohn Marino {
2429e4b17023SJohn Marino hash += (unsigned) USE;
2430e4b17023SJohn Marino x = XEXP (x, 0);
2431e4b17023SJohn Marino
2432e4b17023SJohn Marino if (hash_arg_in_memory_p && !MEM_READONLY_P (x))
2433e4b17023SJohn Marino *hash_arg_in_memory_p = 1;
2434e4b17023SJohn Marino
2435e4b17023SJohn Marino /* Now that we have already found this special case,
2436e4b17023SJohn Marino might as well speed it up as much as possible. */
2437e4b17023SJohn Marino hash += (unsigned) MEM;
2438e4b17023SJohn Marino x = XEXP (x, 0);
2439e4b17023SJohn Marino goto repeat;
2440e4b17023SJohn Marino }
2441e4b17023SJohn Marino break;
2442e4b17023SJohn Marino
2443e4b17023SJohn Marino case PRE_DEC:
2444e4b17023SJohn Marino case PRE_INC:
2445e4b17023SJohn Marino case POST_DEC:
2446e4b17023SJohn Marino case POST_INC:
2447e4b17023SJohn Marino case PRE_MODIFY:
2448e4b17023SJohn Marino case POST_MODIFY:
2449e4b17023SJohn Marino case PC:
2450e4b17023SJohn Marino case CC0:
2451e4b17023SJohn Marino case CALL:
2452e4b17023SJohn Marino case UNSPEC_VOLATILE:
2453e4b17023SJohn Marino if (do_not_record_p) {
2454e4b17023SJohn Marino *do_not_record_p = 1;
2455e4b17023SJohn Marino return 0;
2456e4b17023SJohn Marino }
2457e4b17023SJohn Marino else
2458e4b17023SJohn Marino return hash;
2459e4b17023SJohn Marino break;
2460e4b17023SJohn Marino
2461e4b17023SJohn Marino case ASM_OPERANDS:
2462e4b17023SJohn Marino if (do_not_record_p && MEM_VOLATILE_P (x))
2463e4b17023SJohn Marino {
2464e4b17023SJohn Marino *do_not_record_p = 1;
2465e4b17023SJohn Marino return 0;
2466e4b17023SJohn Marino }
2467e4b17023SJohn Marino else
2468e4b17023SJohn Marino {
2469e4b17023SJohn Marino /* We don't want to take the filename and line into account. */
2470e4b17023SJohn Marino hash += (unsigned) code + (unsigned) GET_MODE (x)
2471e4b17023SJohn Marino + hash_rtx_string (ASM_OPERANDS_TEMPLATE (x))
2472e4b17023SJohn Marino + hash_rtx_string (ASM_OPERANDS_OUTPUT_CONSTRAINT (x))
2473e4b17023SJohn Marino + (unsigned) ASM_OPERANDS_OUTPUT_IDX (x);
2474e4b17023SJohn Marino
2475e4b17023SJohn Marino if (ASM_OPERANDS_INPUT_LENGTH (x))
2476e4b17023SJohn Marino {
2477e4b17023SJohn Marino for (i = 1; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
2478e4b17023SJohn Marino {
2479e4b17023SJohn Marino hash += (hash_rtx_cb (ASM_OPERANDS_INPUT (x, i),
2480e4b17023SJohn Marino GET_MODE (ASM_OPERANDS_INPUT (x, i)),
2481e4b17023SJohn Marino do_not_record_p, hash_arg_in_memory_p,
2482e4b17023SJohn Marino have_reg_qty, cb)
2483e4b17023SJohn Marino + hash_rtx_string
2484e4b17023SJohn Marino (ASM_OPERANDS_INPUT_CONSTRAINT (x, i)));
2485e4b17023SJohn Marino }
2486e4b17023SJohn Marino
2487e4b17023SJohn Marino hash += hash_rtx_string (ASM_OPERANDS_INPUT_CONSTRAINT (x, 0));
2488e4b17023SJohn Marino x = ASM_OPERANDS_INPUT (x, 0);
2489e4b17023SJohn Marino mode = GET_MODE (x);
2490e4b17023SJohn Marino goto repeat;
2491e4b17023SJohn Marino }
2492e4b17023SJohn Marino
2493e4b17023SJohn Marino return hash;
2494e4b17023SJohn Marino }
2495e4b17023SJohn Marino break;
2496e4b17023SJohn Marino
2497e4b17023SJohn Marino default:
2498e4b17023SJohn Marino break;
2499e4b17023SJohn Marino }
2500e4b17023SJohn Marino
2501e4b17023SJohn Marino i = GET_RTX_LENGTH (code) - 1;
2502e4b17023SJohn Marino hash += (unsigned) code + (unsigned) GET_MODE (x);
2503e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
2504e4b17023SJohn Marino for (; i >= 0; i--)
2505e4b17023SJohn Marino {
2506e4b17023SJohn Marino switch (fmt[i])
2507e4b17023SJohn Marino {
2508e4b17023SJohn Marino case 'e':
2509e4b17023SJohn Marino /* If we are about to do the last recursive call
2510e4b17023SJohn Marino needed at this level, change it into iteration.
2511e4b17023SJohn Marino This function is called enough to be worth it. */
2512e4b17023SJohn Marino if (i == 0)
2513e4b17023SJohn Marino {
2514e4b17023SJohn Marino x = XEXP (x, i);
2515e4b17023SJohn Marino goto repeat;
2516e4b17023SJohn Marino }
2517e4b17023SJohn Marino
2518e4b17023SJohn Marino hash += hash_rtx_cb (XEXP (x, i), VOIDmode, do_not_record_p,
2519e4b17023SJohn Marino hash_arg_in_memory_p,
2520e4b17023SJohn Marino have_reg_qty, cb);
2521e4b17023SJohn Marino break;
2522e4b17023SJohn Marino
2523e4b17023SJohn Marino case 'E':
2524e4b17023SJohn Marino for (j = 0; j < XVECLEN (x, i); j++)
2525e4b17023SJohn Marino hash += hash_rtx_cb (XVECEXP (x, i, j), VOIDmode, do_not_record_p,
2526e4b17023SJohn Marino hash_arg_in_memory_p,
2527e4b17023SJohn Marino have_reg_qty, cb);
2528e4b17023SJohn Marino break;
2529e4b17023SJohn Marino
2530e4b17023SJohn Marino case 's':
2531e4b17023SJohn Marino hash += hash_rtx_string (XSTR (x, i));
2532e4b17023SJohn Marino break;
2533e4b17023SJohn Marino
2534e4b17023SJohn Marino case 'i':
2535e4b17023SJohn Marino hash += (unsigned int) XINT (x, i);
2536e4b17023SJohn Marino break;
2537e4b17023SJohn Marino
2538e4b17023SJohn Marino case '0': case 't':
2539e4b17023SJohn Marino /* Unused. */
2540e4b17023SJohn Marino break;
2541e4b17023SJohn Marino
2542e4b17023SJohn Marino default:
2543e4b17023SJohn Marino gcc_unreachable ();
2544e4b17023SJohn Marino }
2545e4b17023SJohn Marino }
2546e4b17023SJohn Marino
2547e4b17023SJohn Marino return hash;
2548e4b17023SJohn Marino }
2549e4b17023SJohn Marino
2550e4b17023SJohn Marino /* Hash an rtx. We are careful to make sure the value is never negative.
2551e4b17023SJohn Marino Equivalent registers hash identically.
2552e4b17023SJohn Marino MODE is used in hashing for CONST_INTs only;
2553e4b17023SJohn Marino otherwise the mode of X is used.
2554e4b17023SJohn Marino
2555e4b17023SJohn Marino Store 1 in DO_NOT_RECORD_P if any subexpression is volatile.
2556e4b17023SJohn Marino
2557e4b17023SJohn Marino If HASH_ARG_IN_MEMORY_P is not NULL, store 1 in it if X contains
2558*5ce9237cSJohn Marino a MEM rtx which does not have the MEM_READONLY_P flag set.
2559e4b17023SJohn Marino
2560e4b17023SJohn Marino Note that cse_insn knows that the hash code of a MEM expression
2561e4b17023SJohn Marino is just (int) MEM plus the hash code of the address. */
2562e4b17023SJohn Marino
2563e4b17023SJohn Marino unsigned
hash_rtx(const_rtx x,enum machine_mode mode,int * do_not_record_p,int * hash_arg_in_memory_p,bool have_reg_qty)2564e4b17023SJohn Marino hash_rtx (const_rtx x, enum machine_mode mode, int *do_not_record_p,
2565e4b17023SJohn Marino int *hash_arg_in_memory_p, bool have_reg_qty)
2566e4b17023SJohn Marino {
2567e4b17023SJohn Marino return hash_rtx_cb (x, mode, do_not_record_p,
2568e4b17023SJohn Marino hash_arg_in_memory_p, have_reg_qty, NULL);
2569e4b17023SJohn Marino }
2570e4b17023SJohn Marino
2571e4b17023SJohn Marino /* Hash an rtx X for cse via hash_rtx.
2572e4b17023SJohn Marino Stores 1 in do_not_record if any subexpression is volatile.
2573e4b17023SJohn Marino Stores 1 in hash_arg_in_memory if X contains a mem rtx which
2574*5ce9237cSJohn Marino does not have the MEM_READONLY_P flag set. */
2575e4b17023SJohn Marino
2576e4b17023SJohn Marino static inline unsigned
canon_hash(rtx x,enum machine_mode mode)2577e4b17023SJohn Marino canon_hash (rtx x, enum machine_mode mode)
2578e4b17023SJohn Marino {
2579e4b17023SJohn Marino return hash_rtx (x, mode, &do_not_record, &hash_arg_in_memory, true);
2580e4b17023SJohn Marino }
2581e4b17023SJohn Marino
2582e4b17023SJohn Marino /* Like canon_hash but with no side effects, i.e. do_not_record
2583e4b17023SJohn Marino and hash_arg_in_memory are not changed. */
2584e4b17023SJohn Marino
2585e4b17023SJohn Marino static inline unsigned
safe_hash(rtx x,enum machine_mode mode)2586e4b17023SJohn Marino safe_hash (rtx x, enum machine_mode mode)
2587e4b17023SJohn Marino {
2588e4b17023SJohn Marino int dummy_do_not_record;
2589e4b17023SJohn Marino return hash_rtx (x, mode, &dummy_do_not_record, NULL, true);
2590e4b17023SJohn Marino }
2591e4b17023SJohn Marino
2592e4b17023SJohn Marino /* Return 1 iff X and Y would canonicalize into the same thing,
2593e4b17023SJohn Marino without actually constructing the canonicalization of either one.
2594e4b17023SJohn Marino If VALIDATE is nonzero,
2595e4b17023SJohn Marino we assume X is an expression being processed from the rtl
2596e4b17023SJohn Marino and Y was found in the hash table. We check register refs
2597e4b17023SJohn Marino in Y for being marked as valid.
2598e4b17023SJohn Marino
2599e4b17023SJohn Marino If FOR_GCSE is true, we compare X and Y for equivalence for GCSE. */
2600e4b17023SJohn Marino
2601e4b17023SJohn Marino int
exp_equiv_p(const_rtx x,const_rtx y,int validate,bool for_gcse)2602e4b17023SJohn Marino exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse)
2603e4b17023SJohn Marino {
2604e4b17023SJohn Marino int i, j;
2605e4b17023SJohn Marino enum rtx_code code;
2606e4b17023SJohn Marino const char *fmt;
2607e4b17023SJohn Marino
2608e4b17023SJohn Marino /* Note: it is incorrect to assume an expression is equivalent to itself
2609e4b17023SJohn Marino if VALIDATE is nonzero. */
2610e4b17023SJohn Marino if (x == y && !validate)
2611e4b17023SJohn Marino return 1;
2612e4b17023SJohn Marino
2613e4b17023SJohn Marino if (x == 0 || y == 0)
2614e4b17023SJohn Marino return x == y;
2615e4b17023SJohn Marino
2616e4b17023SJohn Marino code = GET_CODE (x);
2617e4b17023SJohn Marino if (code != GET_CODE (y))
2618e4b17023SJohn Marino return 0;
2619e4b17023SJohn Marino
2620e4b17023SJohn Marino /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
2621e4b17023SJohn Marino if (GET_MODE (x) != GET_MODE (y))
2622e4b17023SJohn Marino return 0;
2623e4b17023SJohn Marino
2624e4b17023SJohn Marino /* MEMs refering to different address space are not equivalent. */
2625e4b17023SJohn Marino if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y))
2626e4b17023SJohn Marino return 0;
2627e4b17023SJohn Marino
2628e4b17023SJohn Marino switch (code)
2629e4b17023SJohn Marino {
2630e4b17023SJohn Marino case PC:
2631e4b17023SJohn Marino case CC0:
2632e4b17023SJohn Marino case CONST_INT:
2633e4b17023SJohn Marino case CONST_DOUBLE:
2634e4b17023SJohn Marino case CONST_FIXED:
2635e4b17023SJohn Marino return x == y;
2636e4b17023SJohn Marino
2637e4b17023SJohn Marino case LABEL_REF:
2638e4b17023SJohn Marino return XEXP (x, 0) == XEXP (y, 0);
2639e4b17023SJohn Marino
2640e4b17023SJohn Marino case SYMBOL_REF:
2641e4b17023SJohn Marino return XSTR (x, 0) == XSTR (y, 0);
2642e4b17023SJohn Marino
2643e4b17023SJohn Marino case REG:
2644e4b17023SJohn Marino if (for_gcse)
2645e4b17023SJohn Marino return REGNO (x) == REGNO (y);
2646e4b17023SJohn Marino else
2647e4b17023SJohn Marino {
2648e4b17023SJohn Marino unsigned int regno = REGNO (y);
2649e4b17023SJohn Marino unsigned int i;
2650e4b17023SJohn Marino unsigned int endregno = END_REGNO (y);
2651e4b17023SJohn Marino
2652e4b17023SJohn Marino /* If the quantities are not the same, the expressions are not
2653e4b17023SJohn Marino equivalent. If there are and we are not to validate, they
2654e4b17023SJohn Marino are equivalent. Otherwise, ensure all regs are up-to-date. */
2655e4b17023SJohn Marino
2656e4b17023SJohn Marino if (REG_QTY (REGNO (x)) != REG_QTY (regno))
2657e4b17023SJohn Marino return 0;
2658e4b17023SJohn Marino
2659e4b17023SJohn Marino if (! validate)
2660e4b17023SJohn Marino return 1;
2661e4b17023SJohn Marino
2662e4b17023SJohn Marino for (i = regno; i < endregno; i++)
2663e4b17023SJohn Marino if (REG_IN_TABLE (i) != REG_TICK (i))
2664e4b17023SJohn Marino return 0;
2665e4b17023SJohn Marino
2666e4b17023SJohn Marino return 1;
2667e4b17023SJohn Marino }
2668e4b17023SJohn Marino
2669e4b17023SJohn Marino case MEM:
2670e4b17023SJohn Marino if (for_gcse)
2671e4b17023SJohn Marino {
2672e4b17023SJohn Marino /* A volatile mem should not be considered equivalent to any
2673e4b17023SJohn Marino other. */
2674e4b17023SJohn Marino if (MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
2675e4b17023SJohn Marino return 0;
2676e4b17023SJohn Marino
2677e4b17023SJohn Marino /* Can't merge two expressions in different alias sets, since we
2678e4b17023SJohn Marino can decide that the expression is transparent in a block when
2679e4b17023SJohn Marino it isn't, due to it being set with the different alias set.
2680e4b17023SJohn Marino
2681e4b17023SJohn Marino Also, can't merge two expressions with different MEM_ATTRS.
2682e4b17023SJohn Marino They could e.g. be two different entities allocated into the
2683e4b17023SJohn Marino same space on the stack (see e.g. PR25130). In that case, the
2684e4b17023SJohn Marino MEM addresses can be the same, even though the two MEMs are
2685e4b17023SJohn Marino absolutely not equivalent.
2686e4b17023SJohn Marino
2687e4b17023SJohn Marino But because really all MEM attributes should be the same for
2688e4b17023SJohn Marino equivalent MEMs, we just use the invariant that MEMs that have
2689e4b17023SJohn Marino the same attributes share the same mem_attrs data structure. */
2690e4b17023SJohn Marino if (MEM_ATTRS (x) != MEM_ATTRS (y))
2691e4b17023SJohn Marino return 0;
2692e4b17023SJohn Marino }
2693e4b17023SJohn Marino break;
2694e4b17023SJohn Marino
2695e4b17023SJohn Marino /* For commutative operations, check both orders. */
2696e4b17023SJohn Marino case PLUS:
2697e4b17023SJohn Marino case MULT:
2698e4b17023SJohn Marino case AND:
2699e4b17023SJohn Marino case IOR:
2700e4b17023SJohn Marino case XOR:
2701e4b17023SJohn Marino case NE:
2702e4b17023SJohn Marino case EQ:
2703e4b17023SJohn Marino return ((exp_equiv_p (XEXP (x, 0), XEXP (y, 0),
2704e4b17023SJohn Marino validate, for_gcse)
2705e4b17023SJohn Marino && exp_equiv_p (XEXP (x, 1), XEXP (y, 1),
2706e4b17023SJohn Marino validate, for_gcse))
2707e4b17023SJohn Marino || (exp_equiv_p (XEXP (x, 0), XEXP (y, 1),
2708e4b17023SJohn Marino validate, for_gcse)
2709e4b17023SJohn Marino && exp_equiv_p (XEXP (x, 1), XEXP (y, 0),
2710e4b17023SJohn Marino validate, for_gcse)));
2711e4b17023SJohn Marino
2712e4b17023SJohn Marino case ASM_OPERANDS:
2713e4b17023SJohn Marino /* We don't use the generic code below because we want to
2714e4b17023SJohn Marino disregard filename and line numbers. */
2715e4b17023SJohn Marino
2716e4b17023SJohn Marino /* A volatile asm isn't equivalent to any other. */
2717e4b17023SJohn Marino if (MEM_VOLATILE_P (x) || MEM_VOLATILE_P (y))
2718e4b17023SJohn Marino return 0;
2719e4b17023SJohn Marino
2720e4b17023SJohn Marino if (GET_MODE (x) != GET_MODE (y)
2721e4b17023SJohn Marino || strcmp (ASM_OPERANDS_TEMPLATE (x), ASM_OPERANDS_TEMPLATE (y))
2722e4b17023SJohn Marino || strcmp (ASM_OPERANDS_OUTPUT_CONSTRAINT (x),
2723e4b17023SJohn Marino ASM_OPERANDS_OUTPUT_CONSTRAINT (y))
2724e4b17023SJohn Marino || ASM_OPERANDS_OUTPUT_IDX (x) != ASM_OPERANDS_OUTPUT_IDX (y)
2725e4b17023SJohn Marino || ASM_OPERANDS_INPUT_LENGTH (x) != ASM_OPERANDS_INPUT_LENGTH (y))
2726e4b17023SJohn Marino return 0;
2727e4b17023SJohn Marino
2728e4b17023SJohn Marino if (ASM_OPERANDS_INPUT_LENGTH (x))
2729e4b17023SJohn Marino {
2730e4b17023SJohn Marino for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
2731e4b17023SJohn Marino if (! exp_equiv_p (ASM_OPERANDS_INPUT (x, i),
2732e4b17023SJohn Marino ASM_OPERANDS_INPUT (y, i),
2733e4b17023SJohn Marino validate, for_gcse)
2734e4b17023SJohn Marino || strcmp (ASM_OPERANDS_INPUT_CONSTRAINT (x, i),
2735e4b17023SJohn Marino ASM_OPERANDS_INPUT_CONSTRAINT (y, i)))
2736e4b17023SJohn Marino return 0;
2737e4b17023SJohn Marino }
2738e4b17023SJohn Marino
2739e4b17023SJohn Marino return 1;
2740e4b17023SJohn Marino
2741e4b17023SJohn Marino default:
2742e4b17023SJohn Marino break;
2743e4b17023SJohn Marino }
2744e4b17023SJohn Marino
2745e4b17023SJohn Marino /* Compare the elements. If any pair of corresponding elements
2746e4b17023SJohn Marino fail to match, return 0 for the whole thing. */
2747e4b17023SJohn Marino
2748e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
2749e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2750e4b17023SJohn Marino {
2751e4b17023SJohn Marino switch (fmt[i])
2752e4b17023SJohn Marino {
2753e4b17023SJohn Marino case 'e':
2754e4b17023SJohn Marino if (! exp_equiv_p (XEXP (x, i), XEXP (y, i),
2755e4b17023SJohn Marino validate, for_gcse))
2756e4b17023SJohn Marino return 0;
2757e4b17023SJohn Marino break;
2758e4b17023SJohn Marino
2759e4b17023SJohn Marino case 'E':
2760e4b17023SJohn Marino if (XVECLEN (x, i) != XVECLEN (y, i))
2761e4b17023SJohn Marino return 0;
2762e4b17023SJohn Marino for (j = 0; j < XVECLEN (x, i); j++)
2763e4b17023SJohn Marino if (! exp_equiv_p (XVECEXP (x, i, j), XVECEXP (y, i, j),
2764e4b17023SJohn Marino validate, for_gcse))
2765e4b17023SJohn Marino return 0;
2766e4b17023SJohn Marino break;
2767e4b17023SJohn Marino
2768e4b17023SJohn Marino case 's':
2769e4b17023SJohn Marino if (strcmp (XSTR (x, i), XSTR (y, i)))
2770e4b17023SJohn Marino return 0;
2771e4b17023SJohn Marino break;
2772e4b17023SJohn Marino
2773e4b17023SJohn Marino case 'i':
2774e4b17023SJohn Marino if (XINT (x, i) != XINT (y, i))
2775e4b17023SJohn Marino return 0;
2776e4b17023SJohn Marino break;
2777e4b17023SJohn Marino
2778e4b17023SJohn Marino case 'w':
2779e4b17023SJohn Marino if (XWINT (x, i) != XWINT (y, i))
2780e4b17023SJohn Marino return 0;
2781e4b17023SJohn Marino break;
2782e4b17023SJohn Marino
2783e4b17023SJohn Marino case '0':
2784e4b17023SJohn Marino case 't':
2785e4b17023SJohn Marino break;
2786e4b17023SJohn Marino
2787e4b17023SJohn Marino default:
2788e4b17023SJohn Marino gcc_unreachable ();
2789e4b17023SJohn Marino }
2790e4b17023SJohn Marino }
2791e4b17023SJohn Marino
2792e4b17023SJohn Marino return 1;
2793e4b17023SJohn Marino }
2794e4b17023SJohn Marino
2795e4b17023SJohn Marino /* Subroutine of canon_reg. Pass *XLOC through canon_reg, and validate
2796e4b17023SJohn Marino the result if necessary. INSN is as for canon_reg. */
2797e4b17023SJohn Marino
2798e4b17023SJohn Marino static void
validate_canon_reg(rtx * xloc,rtx insn)2799e4b17023SJohn Marino validate_canon_reg (rtx *xloc, rtx insn)
2800e4b17023SJohn Marino {
2801e4b17023SJohn Marino if (*xloc)
2802e4b17023SJohn Marino {
2803e4b17023SJohn Marino rtx new_rtx = canon_reg (*xloc, insn);
2804e4b17023SJohn Marino
2805e4b17023SJohn Marino /* If replacing pseudo with hard reg or vice versa, ensure the
2806e4b17023SJohn Marino insn remains valid. Likewise if the insn has MATCH_DUPs. */
2807e4b17023SJohn Marino gcc_assert (insn && new_rtx);
2808e4b17023SJohn Marino validate_change (insn, xloc, new_rtx, 1);
2809e4b17023SJohn Marino }
2810e4b17023SJohn Marino }
2811e4b17023SJohn Marino
2812e4b17023SJohn Marino /* Canonicalize an expression:
2813e4b17023SJohn Marino replace each register reference inside it
2814e4b17023SJohn Marino with the "oldest" equivalent register.
2815e4b17023SJohn Marino
2816e4b17023SJohn Marino If INSN is nonzero validate_change is used to ensure that INSN remains valid
2817e4b17023SJohn Marino after we make our substitution. The calls are made with IN_GROUP nonzero
2818e4b17023SJohn Marino so apply_change_group must be called upon the outermost return from this
2819e4b17023SJohn Marino function (unless INSN is zero). The result of apply_change_group can
2820e4b17023SJohn Marino generally be discarded since the changes we are making are optional. */
2821e4b17023SJohn Marino
2822e4b17023SJohn Marino static rtx
canon_reg(rtx x,rtx insn)2823e4b17023SJohn Marino canon_reg (rtx x, rtx insn)
2824e4b17023SJohn Marino {
2825e4b17023SJohn Marino int i;
2826e4b17023SJohn Marino enum rtx_code code;
2827e4b17023SJohn Marino const char *fmt;
2828e4b17023SJohn Marino
2829e4b17023SJohn Marino if (x == 0)
2830e4b17023SJohn Marino return x;
2831e4b17023SJohn Marino
2832e4b17023SJohn Marino code = GET_CODE (x);
2833e4b17023SJohn Marino switch (code)
2834e4b17023SJohn Marino {
2835e4b17023SJohn Marino case PC:
2836e4b17023SJohn Marino case CC0:
2837e4b17023SJohn Marino case CONST:
2838e4b17023SJohn Marino case CONST_INT:
2839e4b17023SJohn Marino case CONST_DOUBLE:
2840e4b17023SJohn Marino case CONST_FIXED:
2841e4b17023SJohn Marino case CONST_VECTOR:
2842e4b17023SJohn Marino case SYMBOL_REF:
2843e4b17023SJohn Marino case LABEL_REF:
2844e4b17023SJohn Marino case ADDR_VEC:
2845e4b17023SJohn Marino case ADDR_DIFF_VEC:
2846e4b17023SJohn Marino return x;
2847e4b17023SJohn Marino
2848e4b17023SJohn Marino case REG:
2849e4b17023SJohn Marino {
2850e4b17023SJohn Marino int first;
2851e4b17023SJohn Marino int q;
2852e4b17023SJohn Marino struct qty_table_elem *ent;
2853e4b17023SJohn Marino
2854e4b17023SJohn Marino /* Never replace a hard reg, because hard regs can appear
2855e4b17023SJohn Marino in more than one machine mode, and we must preserve the mode
2856e4b17023SJohn Marino of each occurrence. Also, some hard regs appear in
2857e4b17023SJohn Marino MEMs that are shared and mustn't be altered. Don't try to
2858e4b17023SJohn Marino replace any reg that maps to a reg of class NO_REGS. */
2859e4b17023SJohn Marino if (REGNO (x) < FIRST_PSEUDO_REGISTER
2860e4b17023SJohn Marino || ! REGNO_QTY_VALID_P (REGNO (x)))
2861e4b17023SJohn Marino return x;
2862e4b17023SJohn Marino
2863e4b17023SJohn Marino q = REG_QTY (REGNO (x));
2864e4b17023SJohn Marino ent = &qty_table[q];
2865e4b17023SJohn Marino first = ent->first_reg;
2866e4b17023SJohn Marino return (first >= FIRST_PSEUDO_REGISTER ? regno_reg_rtx[first]
2867e4b17023SJohn Marino : REGNO_REG_CLASS (first) == NO_REGS ? x
2868e4b17023SJohn Marino : gen_rtx_REG (ent->mode, first));
2869e4b17023SJohn Marino }
2870e4b17023SJohn Marino
2871e4b17023SJohn Marino default:
2872e4b17023SJohn Marino break;
2873e4b17023SJohn Marino }
2874e4b17023SJohn Marino
2875e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
2876e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
2877e4b17023SJohn Marino {
2878e4b17023SJohn Marino int j;
2879e4b17023SJohn Marino
2880e4b17023SJohn Marino if (fmt[i] == 'e')
2881e4b17023SJohn Marino validate_canon_reg (&XEXP (x, i), insn);
2882e4b17023SJohn Marino else if (fmt[i] == 'E')
2883e4b17023SJohn Marino for (j = 0; j < XVECLEN (x, i); j++)
2884e4b17023SJohn Marino validate_canon_reg (&XVECEXP (x, i, j), insn);
2885e4b17023SJohn Marino }
2886e4b17023SJohn Marino
2887e4b17023SJohn Marino return x;
2888e4b17023SJohn Marino }
2889e4b17023SJohn Marino
2890e4b17023SJohn Marino /* Given an operation (CODE, *PARG1, *PARG2), where code is a comparison
2891e4b17023SJohn Marino operation (EQ, NE, GT, etc.), follow it back through the hash table and
2892e4b17023SJohn Marino what values are being compared.
2893e4b17023SJohn Marino
2894e4b17023SJohn Marino *PARG1 and *PARG2 are updated to contain the rtx representing the values
2895e4b17023SJohn Marino actually being compared. For example, if *PARG1 was (cc0) and *PARG2
2896e4b17023SJohn Marino was (const_int 0), *PARG1 and *PARG2 will be set to the objects that were
2897e4b17023SJohn Marino compared to produce cc0.
2898e4b17023SJohn Marino
2899e4b17023SJohn Marino The return value is the comparison operator and is either the code of
2900e4b17023SJohn Marino A or the code corresponding to the inverse of the comparison. */
2901e4b17023SJohn Marino
2902e4b17023SJohn Marino static enum rtx_code
find_comparison_args(enum rtx_code code,rtx * parg1,rtx * parg2,enum machine_mode * pmode1,enum machine_mode * pmode2)2903e4b17023SJohn Marino find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
2904e4b17023SJohn Marino enum machine_mode *pmode1, enum machine_mode *pmode2)
2905e4b17023SJohn Marino {
2906e4b17023SJohn Marino rtx arg1, arg2;
2907e4b17023SJohn Marino
2908e4b17023SJohn Marino arg1 = *parg1, arg2 = *parg2;
2909e4b17023SJohn Marino
2910e4b17023SJohn Marino /* If ARG2 is const0_rtx, see what ARG1 is equivalent to. */
2911e4b17023SJohn Marino
2912e4b17023SJohn Marino while (arg2 == CONST0_RTX (GET_MODE (arg1)))
2913e4b17023SJohn Marino {
2914e4b17023SJohn Marino /* Set nonzero when we find something of interest. */
2915e4b17023SJohn Marino rtx x = 0;
2916e4b17023SJohn Marino int reverse_code = 0;
2917e4b17023SJohn Marino struct table_elt *p = 0;
2918e4b17023SJohn Marino
2919e4b17023SJohn Marino /* If arg1 is a COMPARE, extract the comparison arguments from it.
2920e4b17023SJohn Marino On machines with CC0, this is the only case that can occur, since
2921e4b17023SJohn Marino fold_rtx will return the COMPARE or item being compared with zero
2922e4b17023SJohn Marino when given CC0. */
2923e4b17023SJohn Marino
2924e4b17023SJohn Marino if (GET_CODE (arg1) == COMPARE && arg2 == const0_rtx)
2925e4b17023SJohn Marino x = arg1;
2926e4b17023SJohn Marino
2927e4b17023SJohn Marino /* If ARG1 is a comparison operator and CODE is testing for
2928e4b17023SJohn Marino STORE_FLAG_VALUE, get the inner arguments. */
2929e4b17023SJohn Marino
2930e4b17023SJohn Marino else if (COMPARISON_P (arg1))
2931e4b17023SJohn Marino {
2932e4b17023SJohn Marino #ifdef FLOAT_STORE_FLAG_VALUE
2933e4b17023SJohn Marino REAL_VALUE_TYPE fsfv;
2934e4b17023SJohn Marino #endif
2935e4b17023SJohn Marino
2936e4b17023SJohn Marino if (code == NE
2937e4b17023SJohn Marino || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT
2938e4b17023SJohn Marino && code == LT && STORE_FLAG_VALUE == -1)
2939e4b17023SJohn Marino #ifdef FLOAT_STORE_FLAG_VALUE
2940e4b17023SJohn Marino || (SCALAR_FLOAT_MODE_P (GET_MODE (arg1))
2941e4b17023SJohn Marino && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
2942e4b17023SJohn Marino REAL_VALUE_NEGATIVE (fsfv)))
2943e4b17023SJohn Marino #endif
2944e4b17023SJohn Marino )
2945e4b17023SJohn Marino x = arg1;
2946e4b17023SJohn Marino else if (code == EQ
2947e4b17023SJohn Marino || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT
2948e4b17023SJohn Marino && code == GE && STORE_FLAG_VALUE == -1)
2949e4b17023SJohn Marino #ifdef FLOAT_STORE_FLAG_VALUE
2950e4b17023SJohn Marino || (SCALAR_FLOAT_MODE_P (GET_MODE (arg1))
2951e4b17023SJohn Marino && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
2952e4b17023SJohn Marino REAL_VALUE_NEGATIVE (fsfv)))
2953e4b17023SJohn Marino #endif
2954e4b17023SJohn Marino )
2955e4b17023SJohn Marino x = arg1, reverse_code = 1;
2956e4b17023SJohn Marino }
2957e4b17023SJohn Marino
2958e4b17023SJohn Marino /* ??? We could also check for
2959e4b17023SJohn Marino
2960e4b17023SJohn Marino (ne (and (eq (...) (const_int 1))) (const_int 0))
2961e4b17023SJohn Marino
2962e4b17023SJohn Marino and related forms, but let's wait until we see them occurring. */
2963e4b17023SJohn Marino
2964e4b17023SJohn Marino if (x == 0)
2965e4b17023SJohn Marino /* Look up ARG1 in the hash table and see if it has an equivalence
2966e4b17023SJohn Marino that lets us see what is being compared. */
2967e4b17023SJohn Marino p = lookup (arg1, SAFE_HASH (arg1, GET_MODE (arg1)), GET_MODE (arg1));
2968e4b17023SJohn Marino if (p)
2969e4b17023SJohn Marino {
2970e4b17023SJohn Marino p = p->first_same_value;
2971e4b17023SJohn Marino
2972e4b17023SJohn Marino /* If what we compare is already known to be constant, that is as
2973e4b17023SJohn Marino good as it gets.
2974e4b17023SJohn Marino We need to break the loop in this case, because otherwise we
2975e4b17023SJohn Marino can have an infinite loop when looking at a reg that is known
2976e4b17023SJohn Marino to be a constant which is the same as a comparison of a reg
2977e4b17023SJohn Marino against zero which appears later in the insn stream, which in
2978e4b17023SJohn Marino turn is constant and the same as the comparison of the first reg
2979e4b17023SJohn Marino against zero... */
2980e4b17023SJohn Marino if (p->is_const)
2981e4b17023SJohn Marino break;
2982e4b17023SJohn Marino }
2983e4b17023SJohn Marino
2984e4b17023SJohn Marino for (; p; p = p->next_same_value)
2985e4b17023SJohn Marino {
2986e4b17023SJohn Marino enum machine_mode inner_mode = GET_MODE (p->exp);
2987e4b17023SJohn Marino #ifdef FLOAT_STORE_FLAG_VALUE
2988e4b17023SJohn Marino REAL_VALUE_TYPE fsfv;
2989e4b17023SJohn Marino #endif
2990e4b17023SJohn Marino
2991e4b17023SJohn Marino /* If the entry isn't valid, skip it. */
2992e4b17023SJohn Marino if (! exp_equiv_p (p->exp, p->exp, 1, false))
2993e4b17023SJohn Marino continue;
2994e4b17023SJohn Marino
2995e4b17023SJohn Marino /* If it's the same comparison we're already looking at, skip it. */
2996e4b17023SJohn Marino if (COMPARISON_P (p->exp)
2997e4b17023SJohn Marino && XEXP (p->exp, 0) == arg1
2998e4b17023SJohn Marino && XEXP (p->exp, 1) == arg2)
2999e4b17023SJohn Marino continue;
3000e4b17023SJohn Marino
3001e4b17023SJohn Marino if (GET_CODE (p->exp) == COMPARE
3002e4b17023SJohn Marino /* Another possibility is that this machine has a compare insn
3003e4b17023SJohn Marino that includes the comparison code. In that case, ARG1 would
3004e4b17023SJohn Marino be equivalent to a comparison operation that would set ARG1 to
3005e4b17023SJohn Marino either STORE_FLAG_VALUE or zero. If this is an NE operation,
3006e4b17023SJohn Marino ORIG_CODE is the actual comparison being done; if it is an EQ,
3007e4b17023SJohn Marino we must reverse ORIG_CODE. On machine with a negative value
3008e4b17023SJohn Marino for STORE_FLAG_VALUE, also look at LT and GE operations. */
3009e4b17023SJohn Marino || ((code == NE
3010e4b17023SJohn Marino || (code == LT
3011e4b17023SJohn Marino && val_signbit_known_set_p (inner_mode,
3012e4b17023SJohn Marino STORE_FLAG_VALUE))
3013e4b17023SJohn Marino #ifdef FLOAT_STORE_FLAG_VALUE
3014e4b17023SJohn Marino || (code == LT
3015e4b17023SJohn Marino && SCALAR_FLOAT_MODE_P (inner_mode)
3016e4b17023SJohn Marino && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
3017e4b17023SJohn Marino REAL_VALUE_NEGATIVE (fsfv)))
3018e4b17023SJohn Marino #endif
3019e4b17023SJohn Marino )
3020e4b17023SJohn Marino && COMPARISON_P (p->exp)))
3021e4b17023SJohn Marino {
3022e4b17023SJohn Marino x = p->exp;
3023e4b17023SJohn Marino break;
3024e4b17023SJohn Marino }
3025e4b17023SJohn Marino else if ((code == EQ
3026e4b17023SJohn Marino || (code == GE
3027e4b17023SJohn Marino && val_signbit_known_set_p (inner_mode,
3028e4b17023SJohn Marino STORE_FLAG_VALUE))
3029e4b17023SJohn Marino #ifdef FLOAT_STORE_FLAG_VALUE
3030e4b17023SJohn Marino || (code == GE
3031e4b17023SJohn Marino && SCALAR_FLOAT_MODE_P (inner_mode)
3032e4b17023SJohn Marino && (fsfv = FLOAT_STORE_FLAG_VALUE (GET_MODE (arg1)),
3033e4b17023SJohn Marino REAL_VALUE_NEGATIVE (fsfv)))
3034e4b17023SJohn Marino #endif
3035e4b17023SJohn Marino )
3036e4b17023SJohn Marino && COMPARISON_P (p->exp))
3037e4b17023SJohn Marino {
3038e4b17023SJohn Marino reverse_code = 1;
3039e4b17023SJohn Marino x = p->exp;
3040e4b17023SJohn Marino break;
3041e4b17023SJohn Marino }
3042e4b17023SJohn Marino
3043e4b17023SJohn Marino /* If this non-trapping address, e.g. fp + constant, the
3044e4b17023SJohn Marino equivalent is a better operand since it may let us predict
3045e4b17023SJohn Marino the value of the comparison. */
3046e4b17023SJohn Marino else if (!rtx_addr_can_trap_p (p->exp))
3047e4b17023SJohn Marino {
3048e4b17023SJohn Marino arg1 = p->exp;
3049e4b17023SJohn Marino continue;
3050e4b17023SJohn Marino }
3051e4b17023SJohn Marino }
3052e4b17023SJohn Marino
3053e4b17023SJohn Marino /* If we didn't find a useful equivalence for ARG1, we are done.
3054e4b17023SJohn Marino Otherwise, set up for the next iteration. */
3055e4b17023SJohn Marino if (x == 0)
3056e4b17023SJohn Marino break;
3057e4b17023SJohn Marino
3058e4b17023SJohn Marino /* If we need to reverse the comparison, make sure that that is
3059e4b17023SJohn Marino possible -- we can't necessarily infer the value of GE from LT
3060e4b17023SJohn Marino with floating-point operands. */
3061e4b17023SJohn Marino if (reverse_code)
3062e4b17023SJohn Marino {
3063e4b17023SJohn Marino enum rtx_code reversed = reversed_comparison_code (x, NULL_RTX);
3064e4b17023SJohn Marino if (reversed == UNKNOWN)
3065e4b17023SJohn Marino break;
3066e4b17023SJohn Marino else
3067e4b17023SJohn Marino code = reversed;
3068e4b17023SJohn Marino }
3069e4b17023SJohn Marino else if (COMPARISON_P (x))
3070e4b17023SJohn Marino code = GET_CODE (x);
3071e4b17023SJohn Marino arg1 = XEXP (x, 0), arg2 = XEXP (x, 1);
3072e4b17023SJohn Marino }
3073e4b17023SJohn Marino
3074e4b17023SJohn Marino /* Return our results. Return the modes from before fold_rtx
3075e4b17023SJohn Marino because fold_rtx might produce const_int, and then it's too late. */
3076e4b17023SJohn Marino *pmode1 = GET_MODE (arg1), *pmode2 = GET_MODE (arg2);
3077e4b17023SJohn Marino *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
3078e4b17023SJohn Marino
3079e4b17023SJohn Marino return code;
3080e4b17023SJohn Marino }
3081e4b17023SJohn Marino
3082e4b17023SJohn Marino /* If X is a nontrivial arithmetic operation on an argument for which
3083e4b17023SJohn Marino a constant value can be determined, return the result of operating
3084e4b17023SJohn Marino on that value, as a constant. Otherwise, return X, possibly with
3085e4b17023SJohn Marino one or more operands changed to a forward-propagated constant.
3086e4b17023SJohn Marino
3087e4b17023SJohn Marino If X is a register whose contents are known, we do NOT return
3088e4b17023SJohn Marino those contents here; equiv_constant is called to perform that task.
3089e4b17023SJohn Marino For SUBREGs and MEMs, we do that both here and in equiv_constant.
3090e4b17023SJohn Marino
3091e4b17023SJohn Marino INSN is the insn that we may be modifying. If it is 0, make a copy
3092e4b17023SJohn Marino of X before modifying it. */
3093e4b17023SJohn Marino
3094e4b17023SJohn Marino static rtx
fold_rtx(rtx x,rtx insn)3095e4b17023SJohn Marino fold_rtx (rtx x, rtx insn)
3096e4b17023SJohn Marino {
3097e4b17023SJohn Marino enum rtx_code code;
3098e4b17023SJohn Marino enum machine_mode mode;
3099e4b17023SJohn Marino const char *fmt;
3100e4b17023SJohn Marino int i;
3101e4b17023SJohn Marino rtx new_rtx = 0;
3102e4b17023SJohn Marino int changed = 0;
3103e4b17023SJohn Marino
3104e4b17023SJohn Marino /* Operands of X. */
3105e4b17023SJohn Marino rtx folded_arg0;
3106e4b17023SJohn Marino rtx folded_arg1;
3107e4b17023SJohn Marino
3108e4b17023SJohn Marino /* Constant equivalents of first three operands of X;
3109e4b17023SJohn Marino 0 when no such equivalent is known. */
3110e4b17023SJohn Marino rtx const_arg0;
3111e4b17023SJohn Marino rtx const_arg1;
3112e4b17023SJohn Marino rtx const_arg2;
3113e4b17023SJohn Marino
3114e4b17023SJohn Marino /* The mode of the first operand of X. We need this for sign and zero
3115e4b17023SJohn Marino extends. */
3116e4b17023SJohn Marino enum machine_mode mode_arg0;
3117e4b17023SJohn Marino
3118e4b17023SJohn Marino if (x == 0)
3119e4b17023SJohn Marino return x;
3120e4b17023SJohn Marino
3121e4b17023SJohn Marino /* Try to perform some initial simplifications on X. */
3122e4b17023SJohn Marino code = GET_CODE (x);
3123e4b17023SJohn Marino switch (code)
3124e4b17023SJohn Marino {
3125e4b17023SJohn Marino case MEM:
3126e4b17023SJohn Marino case SUBREG:
3127e4b17023SJohn Marino if ((new_rtx = equiv_constant (x)) != NULL_RTX)
3128e4b17023SJohn Marino return new_rtx;
3129e4b17023SJohn Marino return x;
3130e4b17023SJohn Marino
3131e4b17023SJohn Marino case CONST:
3132e4b17023SJohn Marino case CONST_INT:
3133e4b17023SJohn Marino case CONST_DOUBLE:
3134e4b17023SJohn Marino case CONST_FIXED:
3135e4b17023SJohn Marino case CONST_VECTOR:
3136e4b17023SJohn Marino case SYMBOL_REF:
3137e4b17023SJohn Marino case LABEL_REF:
3138e4b17023SJohn Marino case REG:
3139e4b17023SJohn Marino case PC:
3140e4b17023SJohn Marino /* No use simplifying an EXPR_LIST
3141e4b17023SJohn Marino since they are used only for lists of args
3142e4b17023SJohn Marino in a function call's REG_EQUAL note. */
3143e4b17023SJohn Marino case EXPR_LIST:
3144e4b17023SJohn Marino return x;
3145e4b17023SJohn Marino
3146e4b17023SJohn Marino #ifdef HAVE_cc0
3147e4b17023SJohn Marino case CC0:
3148e4b17023SJohn Marino return prev_insn_cc0;
3149e4b17023SJohn Marino #endif
3150e4b17023SJohn Marino
3151e4b17023SJohn Marino case ASM_OPERANDS:
3152e4b17023SJohn Marino if (insn)
3153e4b17023SJohn Marino {
3154e4b17023SJohn Marino for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
3155e4b17023SJohn Marino validate_change (insn, &ASM_OPERANDS_INPUT (x, i),
3156e4b17023SJohn Marino fold_rtx (ASM_OPERANDS_INPUT (x, i), insn), 0);
3157e4b17023SJohn Marino }
3158e4b17023SJohn Marino return x;
3159e4b17023SJohn Marino
3160e4b17023SJohn Marino #ifdef NO_FUNCTION_CSE
3161e4b17023SJohn Marino case CALL:
3162e4b17023SJohn Marino if (CONSTANT_P (XEXP (XEXP (x, 0), 0)))
3163e4b17023SJohn Marino return x;
3164e4b17023SJohn Marino break;
3165e4b17023SJohn Marino #endif
3166e4b17023SJohn Marino
3167e4b17023SJohn Marino /* Anything else goes through the loop below. */
3168e4b17023SJohn Marino default:
3169e4b17023SJohn Marino break;
3170e4b17023SJohn Marino }
3171e4b17023SJohn Marino
3172e4b17023SJohn Marino mode = GET_MODE (x);
3173e4b17023SJohn Marino const_arg0 = 0;
3174e4b17023SJohn Marino const_arg1 = 0;
3175e4b17023SJohn Marino const_arg2 = 0;
3176e4b17023SJohn Marino mode_arg0 = VOIDmode;
3177e4b17023SJohn Marino
3178e4b17023SJohn Marino /* Try folding our operands.
3179e4b17023SJohn Marino Then see which ones have constant values known. */
3180e4b17023SJohn Marino
3181e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
3182e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
3183e4b17023SJohn Marino if (fmt[i] == 'e')
3184e4b17023SJohn Marino {
3185e4b17023SJohn Marino rtx folded_arg = XEXP (x, i), const_arg;
3186e4b17023SJohn Marino enum machine_mode mode_arg = GET_MODE (folded_arg);
3187e4b17023SJohn Marino
3188e4b17023SJohn Marino switch (GET_CODE (folded_arg))
3189e4b17023SJohn Marino {
3190e4b17023SJohn Marino case MEM:
3191e4b17023SJohn Marino case REG:
3192e4b17023SJohn Marino case SUBREG:
3193e4b17023SJohn Marino const_arg = equiv_constant (folded_arg);
3194e4b17023SJohn Marino break;
3195e4b17023SJohn Marino
3196e4b17023SJohn Marino case CONST:
3197e4b17023SJohn Marino case CONST_INT:
3198e4b17023SJohn Marino case SYMBOL_REF:
3199e4b17023SJohn Marino case LABEL_REF:
3200e4b17023SJohn Marino case CONST_DOUBLE:
3201e4b17023SJohn Marino case CONST_FIXED:
3202e4b17023SJohn Marino case CONST_VECTOR:
3203e4b17023SJohn Marino const_arg = folded_arg;
3204e4b17023SJohn Marino break;
3205e4b17023SJohn Marino
3206e4b17023SJohn Marino #ifdef HAVE_cc0
3207e4b17023SJohn Marino case CC0:
3208e4b17023SJohn Marino folded_arg = prev_insn_cc0;
3209e4b17023SJohn Marino mode_arg = prev_insn_cc0_mode;
3210e4b17023SJohn Marino const_arg = equiv_constant (folded_arg);
3211e4b17023SJohn Marino break;
3212e4b17023SJohn Marino #endif
3213e4b17023SJohn Marino
3214e4b17023SJohn Marino default:
3215e4b17023SJohn Marino folded_arg = fold_rtx (folded_arg, insn);
3216e4b17023SJohn Marino const_arg = equiv_constant (folded_arg);
3217e4b17023SJohn Marino break;
3218e4b17023SJohn Marino }
3219e4b17023SJohn Marino
3220e4b17023SJohn Marino /* For the first three operands, see if the operand
3221e4b17023SJohn Marino is constant or equivalent to a constant. */
3222e4b17023SJohn Marino switch (i)
3223e4b17023SJohn Marino {
3224e4b17023SJohn Marino case 0:
3225e4b17023SJohn Marino folded_arg0 = folded_arg;
3226e4b17023SJohn Marino const_arg0 = const_arg;
3227e4b17023SJohn Marino mode_arg0 = mode_arg;
3228e4b17023SJohn Marino break;
3229e4b17023SJohn Marino case 1:
3230e4b17023SJohn Marino folded_arg1 = folded_arg;
3231e4b17023SJohn Marino const_arg1 = const_arg;
3232e4b17023SJohn Marino break;
3233e4b17023SJohn Marino case 2:
3234e4b17023SJohn Marino const_arg2 = const_arg;
3235e4b17023SJohn Marino break;
3236e4b17023SJohn Marino }
3237e4b17023SJohn Marino
3238e4b17023SJohn Marino /* Pick the least expensive of the argument and an equivalent constant
3239e4b17023SJohn Marino argument. */
3240e4b17023SJohn Marino if (const_arg != 0
3241e4b17023SJohn Marino && const_arg != folded_arg
3242e4b17023SJohn Marino && COST_IN (const_arg, code, i) <= COST_IN (folded_arg, code, i)
3243e4b17023SJohn Marino
3244e4b17023SJohn Marino /* It's not safe to substitute the operand of a conversion
3245e4b17023SJohn Marino operator with a constant, as the conversion's identity
3246e4b17023SJohn Marino depends upon the mode of its operand. This optimization
3247e4b17023SJohn Marino is handled by the call to simplify_unary_operation. */
3248e4b17023SJohn Marino && (GET_RTX_CLASS (code) != RTX_UNARY
3249e4b17023SJohn Marino || GET_MODE (const_arg) == mode_arg0
3250e4b17023SJohn Marino || (code != ZERO_EXTEND
3251e4b17023SJohn Marino && code != SIGN_EXTEND
3252e4b17023SJohn Marino && code != TRUNCATE
3253e4b17023SJohn Marino && code != FLOAT_TRUNCATE
3254e4b17023SJohn Marino && code != FLOAT_EXTEND
3255e4b17023SJohn Marino && code != FLOAT
3256e4b17023SJohn Marino && code != FIX
3257e4b17023SJohn Marino && code != UNSIGNED_FLOAT
3258e4b17023SJohn Marino && code != UNSIGNED_FIX)))
3259e4b17023SJohn Marino folded_arg = const_arg;
3260e4b17023SJohn Marino
3261e4b17023SJohn Marino if (folded_arg == XEXP (x, i))
3262e4b17023SJohn Marino continue;
3263e4b17023SJohn Marino
3264e4b17023SJohn Marino if (insn == NULL_RTX && !changed)
3265e4b17023SJohn Marino x = copy_rtx (x);
3266e4b17023SJohn Marino changed = 1;
3267e4b17023SJohn Marino validate_unshare_change (insn, &XEXP (x, i), folded_arg, 1);
3268e4b17023SJohn Marino }
3269e4b17023SJohn Marino
3270e4b17023SJohn Marino if (changed)
3271e4b17023SJohn Marino {
3272e4b17023SJohn Marino /* Canonicalize X if necessary, and keep const_argN and folded_argN
3273e4b17023SJohn Marino consistent with the order in X. */
3274e4b17023SJohn Marino if (canonicalize_change_group (insn, x))
3275e4b17023SJohn Marino {
3276e4b17023SJohn Marino rtx tem;
3277e4b17023SJohn Marino tem = const_arg0, const_arg0 = const_arg1, const_arg1 = tem;
3278e4b17023SJohn Marino tem = folded_arg0, folded_arg0 = folded_arg1, folded_arg1 = tem;
3279e4b17023SJohn Marino }
3280e4b17023SJohn Marino
3281e4b17023SJohn Marino apply_change_group ();
3282e4b17023SJohn Marino }
3283e4b17023SJohn Marino
3284e4b17023SJohn Marino /* If X is an arithmetic operation, see if we can simplify it. */
3285e4b17023SJohn Marino
3286e4b17023SJohn Marino switch (GET_RTX_CLASS (code))
3287e4b17023SJohn Marino {
3288e4b17023SJohn Marino case RTX_UNARY:
3289e4b17023SJohn Marino {
3290e4b17023SJohn Marino /* We can't simplify extension ops unless we know the
3291e4b17023SJohn Marino original mode. */
3292e4b17023SJohn Marino if ((code == ZERO_EXTEND || code == SIGN_EXTEND)
3293e4b17023SJohn Marino && mode_arg0 == VOIDmode)
3294e4b17023SJohn Marino break;
3295e4b17023SJohn Marino
3296e4b17023SJohn Marino new_rtx = simplify_unary_operation (code, mode,
3297e4b17023SJohn Marino const_arg0 ? const_arg0 : folded_arg0,
3298e4b17023SJohn Marino mode_arg0);
3299e4b17023SJohn Marino }
3300e4b17023SJohn Marino break;
3301e4b17023SJohn Marino
3302e4b17023SJohn Marino case RTX_COMPARE:
3303e4b17023SJohn Marino case RTX_COMM_COMPARE:
3304e4b17023SJohn Marino /* See what items are actually being compared and set FOLDED_ARG[01]
3305e4b17023SJohn Marino to those values and CODE to the actual comparison code. If any are
3306e4b17023SJohn Marino constant, set CONST_ARG0 and CONST_ARG1 appropriately. We needn't
3307e4b17023SJohn Marino do anything if both operands are already known to be constant. */
3308e4b17023SJohn Marino
3309e4b17023SJohn Marino /* ??? Vector mode comparisons are not supported yet. */
3310e4b17023SJohn Marino if (VECTOR_MODE_P (mode))
3311e4b17023SJohn Marino break;
3312e4b17023SJohn Marino
3313e4b17023SJohn Marino if (const_arg0 == 0 || const_arg1 == 0)
3314e4b17023SJohn Marino {
3315e4b17023SJohn Marino struct table_elt *p0, *p1;
3316e4b17023SJohn Marino rtx true_rtx, false_rtx;
3317e4b17023SJohn Marino enum machine_mode mode_arg1;
3318e4b17023SJohn Marino
3319e4b17023SJohn Marino if (SCALAR_FLOAT_MODE_P (mode))
3320e4b17023SJohn Marino {
3321e4b17023SJohn Marino #ifdef FLOAT_STORE_FLAG_VALUE
3322e4b17023SJohn Marino true_rtx = (CONST_DOUBLE_FROM_REAL_VALUE
3323e4b17023SJohn Marino (FLOAT_STORE_FLAG_VALUE (mode), mode));
3324e4b17023SJohn Marino #else
3325e4b17023SJohn Marino true_rtx = NULL_RTX;
3326e4b17023SJohn Marino #endif
3327e4b17023SJohn Marino false_rtx = CONST0_RTX (mode);
3328e4b17023SJohn Marino }
3329e4b17023SJohn Marino else
3330e4b17023SJohn Marino {
3331e4b17023SJohn Marino true_rtx = const_true_rtx;
3332e4b17023SJohn Marino false_rtx = const0_rtx;
3333e4b17023SJohn Marino }
3334e4b17023SJohn Marino
3335e4b17023SJohn Marino code = find_comparison_args (code, &folded_arg0, &folded_arg1,
3336e4b17023SJohn Marino &mode_arg0, &mode_arg1);
3337e4b17023SJohn Marino
3338e4b17023SJohn Marino /* If the mode is VOIDmode or a MODE_CC mode, we don't know
3339e4b17023SJohn Marino what kinds of things are being compared, so we can't do
3340e4b17023SJohn Marino anything with this comparison. */
3341e4b17023SJohn Marino
3342e4b17023SJohn Marino if (mode_arg0 == VOIDmode || GET_MODE_CLASS (mode_arg0) == MODE_CC)
3343e4b17023SJohn Marino break;
3344e4b17023SJohn Marino
3345e4b17023SJohn Marino const_arg0 = equiv_constant (folded_arg0);
3346e4b17023SJohn Marino const_arg1 = equiv_constant (folded_arg1);
3347e4b17023SJohn Marino
3348e4b17023SJohn Marino /* If we do not now have two constants being compared, see
3349e4b17023SJohn Marino if we can nevertheless deduce some things about the
3350e4b17023SJohn Marino comparison. */
3351e4b17023SJohn Marino if (const_arg0 == 0 || const_arg1 == 0)
3352e4b17023SJohn Marino {
3353e4b17023SJohn Marino if (const_arg1 != NULL)
3354e4b17023SJohn Marino {
3355e4b17023SJohn Marino rtx cheapest_simplification;
3356e4b17023SJohn Marino int cheapest_cost;
3357e4b17023SJohn Marino rtx simp_result;
3358e4b17023SJohn Marino struct table_elt *p;
3359e4b17023SJohn Marino
3360e4b17023SJohn Marino /* See if we can find an equivalent of folded_arg0
3361e4b17023SJohn Marino that gets us a cheaper expression, possibly a
3362e4b17023SJohn Marino constant through simplifications. */
3363e4b17023SJohn Marino p = lookup (folded_arg0, SAFE_HASH (folded_arg0, mode_arg0),
3364e4b17023SJohn Marino mode_arg0);
3365e4b17023SJohn Marino
3366e4b17023SJohn Marino if (p != NULL)
3367e4b17023SJohn Marino {
3368e4b17023SJohn Marino cheapest_simplification = x;
3369e4b17023SJohn Marino cheapest_cost = COST (x);
3370e4b17023SJohn Marino
3371e4b17023SJohn Marino for (p = p->first_same_value; p != NULL; p = p->next_same_value)
3372e4b17023SJohn Marino {
3373e4b17023SJohn Marino int cost;
3374e4b17023SJohn Marino
3375e4b17023SJohn Marino /* If the entry isn't valid, skip it. */
3376e4b17023SJohn Marino if (! exp_equiv_p (p->exp, p->exp, 1, false))
3377e4b17023SJohn Marino continue;
3378e4b17023SJohn Marino
3379e4b17023SJohn Marino /* Try to simplify using this equivalence. */
3380e4b17023SJohn Marino simp_result
3381e4b17023SJohn Marino = simplify_relational_operation (code, mode,
3382e4b17023SJohn Marino mode_arg0,
3383e4b17023SJohn Marino p->exp,
3384e4b17023SJohn Marino const_arg1);
3385e4b17023SJohn Marino
3386e4b17023SJohn Marino if (simp_result == NULL)
3387e4b17023SJohn Marino continue;
3388e4b17023SJohn Marino
3389e4b17023SJohn Marino cost = COST (simp_result);
3390e4b17023SJohn Marino if (cost < cheapest_cost)
3391e4b17023SJohn Marino {
3392e4b17023SJohn Marino cheapest_cost = cost;
3393e4b17023SJohn Marino cheapest_simplification = simp_result;
3394e4b17023SJohn Marino }
3395e4b17023SJohn Marino }
3396e4b17023SJohn Marino
3397e4b17023SJohn Marino /* If we have a cheaper expression now, use that
3398e4b17023SJohn Marino and try folding it further, from the top. */
3399e4b17023SJohn Marino if (cheapest_simplification != x)
3400e4b17023SJohn Marino return fold_rtx (copy_rtx (cheapest_simplification),
3401e4b17023SJohn Marino insn);
3402e4b17023SJohn Marino }
3403e4b17023SJohn Marino }
3404e4b17023SJohn Marino
3405e4b17023SJohn Marino /* See if the two operands are the same. */
3406e4b17023SJohn Marino
3407e4b17023SJohn Marino if ((REG_P (folded_arg0)
3408e4b17023SJohn Marino && REG_P (folded_arg1)
3409e4b17023SJohn Marino && (REG_QTY (REGNO (folded_arg0))
3410e4b17023SJohn Marino == REG_QTY (REGNO (folded_arg1))))
3411e4b17023SJohn Marino || ((p0 = lookup (folded_arg0,
3412e4b17023SJohn Marino SAFE_HASH (folded_arg0, mode_arg0),
3413e4b17023SJohn Marino mode_arg0))
3414e4b17023SJohn Marino && (p1 = lookup (folded_arg1,
3415e4b17023SJohn Marino SAFE_HASH (folded_arg1, mode_arg0),
3416e4b17023SJohn Marino mode_arg0))
3417e4b17023SJohn Marino && p0->first_same_value == p1->first_same_value))
3418e4b17023SJohn Marino folded_arg1 = folded_arg0;
3419e4b17023SJohn Marino
3420e4b17023SJohn Marino /* If FOLDED_ARG0 is a register, see if the comparison we are
3421e4b17023SJohn Marino doing now is either the same as we did before or the reverse
3422e4b17023SJohn Marino (we only check the reverse if not floating-point). */
3423e4b17023SJohn Marino else if (REG_P (folded_arg0))
3424e4b17023SJohn Marino {
3425e4b17023SJohn Marino int qty = REG_QTY (REGNO (folded_arg0));
3426e4b17023SJohn Marino
3427e4b17023SJohn Marino if (REGNO_QTY_VALID_P (REGNO (folded_arg0)))
3428e4b17023SJohn Marino {
3429e4b17023SJohn Marino struct qty_table_elem *ent = &qty_table[qty];
3430e4b17023SJohn Marino
3431e4b17023SJohn Marino if ((comparison_dominates_p (ent->comparison_code, code)
3432e4b17023SJohn Marino || (! FLOAT_MODE_P (mode_arg0)
3433e4b17023SJohn Marino && comparison_dominates_p (ent->comparison_code,
3434e4b17023SJohn Marino reverse_condition (code))))
3435e4b17023SJohn Marino && (rtx_equal_p (ent->comparison_const, folded_arg1)
3436e4b17023SJohn Marino || (const_arg1
3437e4b17023SJohn Marino && rtx_equal_p (ent->comparison_const,
3438e4b17023SJohn Marino const_arg1))
3439e4b17023SJohn Marino || (REG_P (folded_arg1)
3440e4b17023SJohn Marino && (REG_QTY (REGNO (folded_arg1)) == ent->comparison_qty))))
3441e4b17023SJohn Marino {
3442e4b17023SJohn Marino if (comparison_dominates_p (ent->comparison_code, code))
3443e4b17023SJohn Marino {
3444e4b17023SJohn Marino if (true_rtx)
3445e4b17023SJohn Marino return true_rtx;
3446e4b17023SJohn Marino else
3447e4b17023SJohn Marino break;
3448e4b17023SJohn Marino }
3449e4b17023SJohn Marino else
3450e4b17023SJohn Marino return false_rtx;
3451e4b17023SJohn Marino }
3452e4b17023SJohn Marino }
3453e4b17023SJohn Marino }
3454e4b17023SJohn Marino }
3455e4b17023SJohn Marino }
3456e4b17023SJohn Marino
3457e4b17023SJohn Marino /* If we are comparing against zero, see if the first operand is
3458e4b17023SJohn Marino equivalent to an IOR with a constant. If so, we may be able to
3459e4b17023SJohn Marino determine the result of this comparison. */
3460e4b17023SJohn Marino if (const_arg1 == const0_rtx && !const_arg0)
3461e4b17023SJohn Marino {
3462e4b17023SJohn Marino rtx y = lookup_as_function (folded_arg0, IOR);
3463e4b17023SJohn Marino rtx inner_const;
3464e4b17023SJohn Marino
3465e4b17023SJohn Marino if (y != 0
3466e4b17023SJohn Marino && (inner_const = equiv_constant (XEXP (y, 1))) != 0
3467e4b17023SJohn Marino && CONST_INT_P (inner_const)
3468e4b17023SJohn Marino && INTVAL (inner_const) != 0)
3469e4b17023SJohn Marino folded_arg0 = gen_rtx_IOR (mode_arg0, XEXP (y, 0), inner_const);
3470e4b17023SJohn Marino }
3471e4b17023SJohn Marino
3472e4b17023SJohn Marino {
3473e4b17023SJohn Marino rtx op0 = const_arg0 ? const_arg0 : folded_arg0;
3474e4b17023SJohn Marino rtx op1 = const_arg1 ? const_arg1 : folded_arg1;
3475e4b17023SJohn Marino new_rtx = simplify_relational_operation (code, mode, mode_arg0, op0, op1);
3476e4b17023SJohn Marino }
3477e4b17023SJohn Marino break;
3478e4b17023SJohn Marino
3479e4b17023SJohn Marino case RTX_BIN_ARITH:
3480e4b17023SJohn Marino case RTX_COMM_ARITH:
3481e4b17023SJohn Marino switch (code)
3482e4b17023SJohn Marino {
3483e4b17023SJohn Marino case PLUS:
3484e4b17023SJohn Marino /* If the second operand is a LABEL_REF, see if the first is a MINUS
3485e4b17023SJohn Marino with that LABEL_REF as its second operand. If so, the result is
3486e4b17023SJohn Marino the first operand of that MINUS. This handles switches with an
3487e4b17023SJohn Marino ADDR_DIFF_VEC table. */
3488e4b17023SJohn Marino if (const_arg1 && GET_CODE (const_arg1) == LABEL_REF)
3489e4b17023SJohn Marino {
3490e4b17023SJohn Marino rtx y
3491e4b17023SJohn Marino = GET_CODE (folded_arg0) == MINUS ? folded_arg0
3492e4b17023SJohn Marino : lookup_as_function (folded_arg0, MINUS);
3493e4b17023SJohn Marino
3494e4b17023SJohn Marino if (y != 0 && GET_CODE (XEXP (y, 1)) == LABEL_REF
3495e4b17023SJohn Marino && XEXP (XEXP (y, 1), 0) == XEXP (const_arg1, 0))
3496e4b17023SJohn Marino return XEXP (y, 0);
3497e4b17023SJohn Marino
3498e4b17023SJohn Marino /* Now try for a CONST of a MINUS like the above. */
3499e4b17023SJohn Marino if ((y = (GET_CODE (folded_arg0) == CONST ? folded_arg0
3500e4b17023SJohn Marino : lookup_as_function (folded_arg0, CONST))) != 0
3501e4b17023SJohn Marino && GET_CODE (XEXP (y, 0)) == MINUS
3502e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (y, 0), 1)) == LABEL_REF
3503e4b17023SJohn Marino && XEXP (XEXP (XEXP (y, 0), 1), 0) == XEXP (const_arg1, 0))
3504e4b17023SJohn Marino return XEXP (XEXP (y, 0), 0);
3505e4b17023SJohn Marino }
3506e4b17023SJohn Marino
3507e4b17023SJohn Marino /* Likewise if the operands are in the other order. */
3508e4b17023SJohn Marino if (const_arg0 && GET_CODE (const_arg0) == LABEL_REF)
3509e4b17023SJohn Marino {
3510e4b17023SJohn Marino rtx y
3511e4b17023SJohn Marino = GET_CODE (folded_arg1) == MINUS ? folded_arg1
3512e4b17023SJohn Marino : lookup_as_function (folded_arg1, MINUS);
3513e4b17023SJohn Marino
3514e4b17023SJohn Marino if (y != 0 && GET_CODE (XEXP (y, 1)) == LABEL_REF
3515e4b17023SJohn Marino && XEXP (XEXP (y, 1), 0) == XEXP (const_arg0, 0))
3516e4b17023SJohn Marino return XEXP (y, 0);
3517e4b17023SJohn Marino
3518e4b17023SJohn Marino /* Now try for a CONST of a MINUS like the above. */
3519e4b17023SJohn Marino if ((y = (GET_CODE (folded_arg1) == CONST ? folded_arg1
3520e4b17023SJohn Marino : lookup_as_function (folded_arg1, CONST))) != 0
3521e4b17023SJohn Marino && GET_CODE (XEXP (y, 0)) == MINUS
3522e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (y, 0), 1)) == LABEL_REF
3523e4b17023SJohn Marino && XEXP (XEXP (XEXP (y, 0), 1), 0) == XEXP (const_arg0, 0))
3524e4b17023SJohn Marino return XEXP (XEXP (y, 0), 0);
3525e4b17023SJohn Marino }
3526e4b17023SJohn Marino
3527e4b17023SJohn Marino /* If second operand is a register equivalent to a negative
3528e4b17023SJohn Marino CONST_INT, see if we can find a register equivalent to the
3529e4b17023SJohn Marino positive constant. Make a MINUS if so. Don't do this for
3530e4b17023SJohn Marino a non-negative constant since we might then alternate between
3531e4b17023SJohn Marino choosing positive and negative constants. Having the positive
3532e4b17023SJohn Marino constant previously-used is the more common case. Be sure
3533e4b17023SJohn Marino the resulting constant is non-negative; if const_arg1 were
3534e4b17023SJohn Marino the smallest negative number this would overflow: depending
3535e4b17023SJohn Marino on the mode, this would either just be the same value (and
3536e4b17023SJohn Marino hence not save anything) or be incorrect. */
3537e4b17023SJohn Marino if (const_arg1 != 0 && CONST_INT_P (const_arg1)
3538e4b17023SJohn Marino && INTVAL (const_arg1) < 0
3539e4b17023SJohn Marino /* This used to test
3540e4b17023SJohn Marino
3541e4b17023SJohn Marino -INTVAL (const_arg1) >= 0
3542e4b17023SJohn Marino
3543e4b17023SJohn Marino But The Sun V5.0 compilers mis-compiled that test. So
3544e4b17023SJohn Marino instead we test for the problematic value in a more direct
3545e4b17023SJohn Marino manner and hope the Sun compilers get it correct. */
3546e4b17023SJohn Marino && INTVAL (const_arg1) !=
3547e4b17023SJohn Marino ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1))
3548e4b17023SJohn Marino && REG_P (folded_arg1))
3549e4b17023SJohn Marino {
3550e4b17023SJohn Marino rtx new_const = GEN_INT (-INTVAL (const_arg1));
3551e4b17023SJohn Marino struct table_elt *p
3552e4b17023SJohn Marino = lookup (new_const, SAFE_HASH (new_const, mode), mode);
3553e4b17023SJohn Marino
3554e4b17023SJohn Marino if (p)
3555e4b17023SJohn Marino for (p = p->first_same_value; p; p = p->next_same_value)
3556e4b17023SJohn Marino if (REG_P (p->exp))
3557e4b17023SJohn Marino return simplify_gen_binary (MINUS, mode, folded_arg0,
3558e4b17023SJohn Marino canon_reg (p->exp, NULL_RTX));
3559e4b17023SJohn Marino }
3560e4b17023SJohn Marino goto from_plus;
3561e4b17023SJohn Marino
3562e4b17023SJohn Marino case MINUS:
3563e4b17023SJohn Marino /* If we have (MINUS Y C), see if Y is known to be (PLUS Z C2).
3564e4b17023SJohn Marino If so, produce (PLUS Z C2-C). */
3565e4b17023SJohn Marino if (const_arg1 != 0 && CONST_INT_P (const_arg1))
3566e4b17023SJohn Marino {
3567e4b17023SJohn Marino rtx y = lookup_as_function (XEXP (x, 0), PLUS);
3568e4b17023SJohn Marino if (y && CONST_INT_P (XEXP (y, 1)))
3569e4b17023SJohn Marino return fold_rtx (plus_constant (copy_rtx (y),
3570e4b17023SJohn Marino -INTVAL (const_arg1)),
3571e4b17023SJohn Marino NULL_RTX);
3572e4b17023SJohn Marino }
3573e4b17023SJohn Marino
3574e4b17023SJohn Marino /* Fall through. */
3575e4b17023SJohn Marino
3576e4b17023SJohn Marino from_plus:
3577e4b17023SJohn Marino case SMIN: case SMAX: case UMIN: case UMAX:
3578e4b17023SJohn Marino case IOR: case AND: case XOR:
3579e4b17023SJohn Marino case MULT:
3580e4b17023SJohn Marino case ASHIFT: case LSHIFTRT: case ASHIFTRT:
3581e4b17023SJohn Marino /* If we have (<op> <reg> <const_int>) for an associative OP and REG
3582e4b17023SJohn Marino is known to be of similar form, we may be able to replace the
3583e4b17023SJohn Marino operation with a combined operation. This may eliminate the
3584e4b17023SJohn Marino intermediate operation if every use is simplified in this way.
3585e4b17023SJohn Marino Note that the similar optimization done by combine.c only works
3586e4b17023SJohn Marino if the intermediate operation's result has only one reference. */
3587e4b17023SJohn Marino
3588e4b17023SJohn Marino if (REG_P (folded_arg0)
3589e4b17023SJohn Marino && const_arg1 && CONST_INT_P (const_arg1))
3590e4b17023SJohn Marino {
3591e4b17023SJohn Marino int is_shift
3592e4b17023SJohn Marino = (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
3593e4b17023SJohn Marino rtx y, inner_const, new_const;
3594e4b17023SJohn Marino rtx canon_const_arg1 = const_arg1;
3595e4b17023SJohn Marino enum rtx_code associate_code;
3596e4b17023SJohn Marino
3597e4b17023SJohn Marino if (is_shift
3598e4b17023SJohn Marino && (INTVAL (const_arg1) >= GET_MODE_PRECISION (mode)
3599e4b17023SJohn Marino || INTVAL (const_arg1) < 0))
3600e4b17023SJohn Marino {
3601e4b17023SJohn Marino if (SHIFT_COUNT_TRUNCATED)
3602e4b17023SJohn Marino canon_const_arg1 = GEN_INT (INTVAL (const_arg1)
3603e4b17023SJohn Marino & (GET_MODE_BITSIZE (mode)
3604e4b17023SJohn Marino - 1));
3605e4b17023SJohn Marino else
3606e4b17023SJohn Marino break;
3607e4b17023SJohn Marino }
3608e4b17023SJohn Marino
3609e4b17023SJohn Marino y = lookup_as_function (folded_arg0, code);
3610e4b17023SJohn Marino if (y == 0)
3611e4b17023SJohn Marino break;
3612e4b17023SJohn Marino
3613e4b17023SJohn Marino /* If we have compiled a statement like
3614e4b17023SJohn Marino "if (x == (x & mask1))", and now are looking at
3615e4b17023SJohn Marino "x & mask2", we will have a case where the first operand
3616e4b17023SJohn Marino of Y is the same as our first operand. Unless we detect
3617e4b17023SJohn Marino this case, an infinite loop will result. */
3618e4b17023SJohn Marino if (XEXP (y, 0) == folded_arg0)
3619e4b17023SJohn Marino break;
3620e4b17023SJohn Marino
3621e4b17023SJohn Marino inner_const = equiv_constant (fold_rtx (XEXP (y, 1), 0));
3622e4b17023SJohn Marino if (!inner_const || !CONST_INT_P (inner_const))
3623e4b17023SJohn Marino break;
3624e4b17023SJohn Marino
3625e4b17023SJohn Marino /* Don't associate these operations if they are a PLUS with the
3626e4b17023SJohn Marino same constant and it is a power of two. These might be doable
3627e4b17023SJohn Marino with a pre- or post-increment. Similarly for two subtracts of
3628e4b17023SJohn Marino identical powers of two with post decrement. */
3629e4b17023SJohn Marino
3630e4b17023SJohn Marino if (code == PLUS && const_arg1 == inner_const
3631e4b17023SJohn Marino && ((HAVE_PRE_INCREMENT
3632e4b17023SJohn Marino && exact_log2 (INTVAL (const_arg1)) >= 0)
3633e4b17023SJohn Marino || (HAVE_POST_INCREMENT
3634e4b17023SJohn Marino && exact_log2 (INTVAL (const_arg1)) >= 0)
3635e4b17023SJohn Marino || (HAVE_PRE_DECREMENT
3636e4b17023SJohn Marino && exact_log2 (- INTVAL (const_arg1)) >= 0)
3637e4b17023SJohn Marino || (HAVE_POST_DECREMENT
3638e4b17023SJohn Marino && exact_log2 (- INTVAL (const_arg1)) >= 0)))
3639e4b17023SJohn Marino break;
3640e4b17023SJohn Marino
3641e4b17023SJohn Marino /* ??? Vector mode shifts by scalar
3642e4b17023SJohn Marino shift operand are not supported yet. */
3643e4b17023SJohn Marino if (is_shift && VECTOR_MODE_P (mode))
3644e4b17023SJohn Marino break;
3645e4b17023SJohn Marino
3646e4b17023SJohn Marino if (is_shift
3647e4b17023SJohn Marino && (INTVAL (inner_const) >= GET_MODE_PRECISION (mode)
3648e4b17023SJohn Marino || INTVAL (inner_const) < 0))
3649e4b17023SJohn Marino {
3650e4b17023SJohn Marino if (SHIFT_COUNT_TRUNCATED)
3651e4b17023SJohn Marino inner_const = GEN_INT (INTVAL (inner_const)
3652e4b17023SJohn Marino & (GET_MODE_BITSIZE (mode) - 1));
3653e4b17023SJohn Marino else
3654e4b17023SJohn Marino break;
3655e4b17023SJohn Marino }
3656e4b17023SJohn Marino
3657e4b17023SJohn Marino /* Compute the code used to compose the constants. For example,
3658e4b17023SJohn Marino A-C1-C2 is A-(C1 + C2), so if CODE == MINUS, we want PLUS. */
3659e4b17023SJohn Marino
3660e4b17023SJohn Marino associate_code = (is_shift || code == MINUS ? PLUS : code);
3661e4b17023SJohn Marino
3662e4b17023SJohn Marino new_const = simplify_binary_operation (associate_code, mode,
3663e4b17023SJohn Marino canon_const_arg1,
3664e4b17023SJohn Marino inner_const);
3665e4b17023SJohn Marino
3666e4b17023SJohn Marino if (new_const == 0)
3667e4b17023SJohn Marino break;
3668e4b17023SJohn Marino
3669e4b17023SJohn Marino /* If we are associating shift operations, don't let this
3670e4b17023SJohn Marino produce a shift of the size of the object or larger.
3671e4b17023SJohn Marino This could occur when we follow a sign-extend by a right
3672e4b17023SJohn Marino shift on a machine that does a sign-extend as a pair
3673e4b17023SJohn Marino of shifts. */
3674e4b17023SJohn Marino
3675e4b17023SJohn Marino if (is_shift
3676e4b17023SJohn Marino && CONST_INT_P (new_const)
3677e4b17023SJohn Marino && INTVAL (new_const) >= GET_MODE_PRECISION (mode))
3678e4b17023SJohn Marino {
3679e4b17023SJohn Marino /* As an exception, we can turn an ASHIFTRT of this
3680e4b17023SJohn Marino form into a shift of the number of bits - 1. */
3681e4b17023SJohn Marino if (code == ASHIFTRT)
3682e4b17023SJohn Marino new_const = GEN_INT (GET_MODE_BITSIZE (mode) - 1);
3683e4b17023SJohn Marino else if (!side_effects_p (XEXP (y, 0)))
3684e4b17023SJohn Marino return CONST0_RTX (mode);
3685e4b17023SJohn Marino else
3686e4b17023SJohn Marino break;
3687e4b17023SJohn Marino }
3688e4b17023SJohn Marino
3689e4b17023SJohn Marino y = copy_rtx (XEXP (y, 0));
3690e4b17023SJohn Marino
3691e4b17023SJohn Marino /* If Y contains our first operand (the most common way this
3692e4b17023SJohn Marino can happen is if Y is a MEM), we would do into an infinite
3693e4b17023SJohn Marino loop if we tried to fold it. So don't in that case. */
3694e4b17023SJohn Marino
3695e4b17023SJohn Marino if (! reg_mentioned_p (folded_arg0, y))
3696e4b17023SJohn Marino y = fold_rtx (y, insn);
3697e4b17023SJohn Marino
3698e4b17023SJohn Marino return simplify_gen_binary (code, mode, y, new_const);
3699e4b17023SJohn Marino }
3700e4b17023SJohn Marino break;
3701e4b17023SJohn Marino
3702e4b17023SJohn Marino case DIV: case UDIV:
3703e4b17023SJohn Marino /* ??? The associative optimization performed immediately above is
3704e4b17023SJohn Marino also possible for DIV and UDIV using associate_code of MULT.
3705e4b17023SJohn Marino However, we would need extra code to verify that the
3706e4b17023SJohn Marino multiplication does not overflow, that is, there is no overflow
3707e4b17023SJohn Marino in the calculation of new_const. */
3708e4b17023SJohn Marino break;
3709e4b17023SJohn Marino
3710e4b17023SJohn Marino default:
3711e4b17023SJohn Marino break;
3712e4b17023SJohn Marino }
3713e4b17023SJohn Marino
3714e4b17023SJohn Marino new_rtx = simplify_binary_operation (code, mode,
3715e4b17023SJohn Marino const_arg0 ? const_arg0 : folded_arg0,
3716e4b17023SJohn Marino const_arg1 ? const_arg1 : folded_arg1);
3717e4b17023SJohn Marino break;
3718e4b17023SJohn Marino
3719e4b17023SJohn Marino case RTX_OBJ:
3720e4b17023SJohn Marino /* (lo_sum (high X) X) is simply X. */
3721e4b17023SJohn Marino if (code == LO_SUM && const_arg0 != 0
3722e4b17023SJohn Marino && GET_CODE (const_arg0) == HIGH
3723e4b17023SJohn Marino && rtx_equal_p (XEXP (const_arg0, 0), const_arg1))
3724e4b17023SJohn Marino return const_arg1;
3725e4b17023SJohn Marino break;
3726e4b17023SJohn Marino
3727e4b17023SJohn Marino case RTX_TERNARY:
3728e4b17023SJohn Marino case RTX_BITFIELD_OPS:
3729e4b17023SJohn Marino new_rtx = simplify_ternary_operation (code, mode, mode_arg0,
3730e4b17023SJohn Marino const_arg0 ? const_arg0 : folded_arg0,
3731e4b17023SJohn Marino const_arg1 ? const_arg1 : folded_arg1,
3732e4b17023SJohn Marino const_arg2 ? const_arg2 : XEXP (x, 2));
3733e4b17023SJohn Marino break;
3734e4b17023SJohn Marino
3735e4b17023SJohn Marino default:
3736e4b17023SJohn Marino break;
3737e4b17023SJohn Marino }
3738e4b17023SJohn Marino
3739e4b17023SJohn Marino return new_rtx ? new_rtx : x;
3740e4b17023SJohn Marino }
3741e4b17023SJohn Marino
3742e4b17023SJohn Marino /* Return a constant value currently equivalent to X.
3743e4b17023SJohn Marino Return 0 if we don't know one. */
3744e4b17023SJohn Marino
3745e4b17023SJohn Marino static rtx
equiv_constant(rtx x)3746e4b17023SJohn Marino equiv_constant (rtx x)
3747e4b17023SJohn Marino {
3748e4b17023SJohn Marino if (REG_P (x)
3749e4b17023SJohn Marino && REGNO_QTY_VALID_P (REGNO (x)))
3750e4b17023SJohn Marino {
3751e4b17023SJohn Marino int x_q = REG_QTY (REGNO (x));
3752e4b17023SJohn Marino struct qty_table_elem *x_ent = &qty_table[x_q];
3753e4b17023SJohn Marino
3754e4b17023SJohn Marino if (x_ent->const_rtx)
3755e4b17023SJohn Marino x = gen_lowpart (GET_MODE (x), x_ent->const_rtx);
3756e4b17023SJohn Marino }
3757e4b17023SJohn Marino
3758e4b17023SJohn Marino if (x == 0 || CONSTANT_P (x))
3759e4b17023SJohn Marino return x;
3760e4b17023SJohn Marino
3761e4b17023SJohn Marino if (GET_CODE (x) == SUBREG)
3762e4b17023SJohn Marino {
3763e4b17023SJohn Marino enum machine_mode mode = GET_MODE (x);
3764e4b17023SJohn Marino enum machine_mode imode = GET_MODE (SUBREG_REG (x));
3765e4b17023SJohn Marino rtx new_rtx;
3766e4b17023SJohn Marino
3767e4b17023SJohn Marino /* See if we previously assigned a constant value to this SUBREG. */
3768e4b17023SJohn Marino if ((new_rtx = lookup_as_function (x, CONST_INT)) != 0
3769e4b17023SJohn Marino || (new_rtx = lookup_as_function (x, CONST_DOUBLE)) != 0
3770e4b17023SJohn Marino || (new_rtx = lookup_as_function (x, CONST_FIXED)) != 0)
3771e4b17023SJohn Marino return new_rtx;
3772e4b17023SJohn Marino
3773e4b17023SJohn Marino /* If we didn't and if doing so makes sense, see if we previously
3774e4b17023SJohn Marino assigned a constant value to the enclosing word mode SUBREG. */
3775e4b17023SJohn Marino if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode)
3776e4b17023SJohn Marino && GET_MODE_SIZE (word_mode) < GET_MODE_SIZE (imode))
3777e4b17023SJohn Marino {
3778e4b17023SJohn Marino int byte = SUBREG_BYTE (x) - subreg_lowpart_offset (mode, word_mode);
3779e4b17023SJohn Marino if (byte >= 0 && (byte % UNITS_PER_WORD) == 0)
3780e4b17023SJohn Marino {
3781e4b17023SJohn Marino rtx y = gen_rtx_SUBREG (word_mode, SUBREG_REG (x), byte);
3782e4b17023SJohn Marino new_rtx = lookup_as_function (y, CONST_INT);
3783e4b17023SJohn Marino if (new_rtx)
3784e4b17023SJohn Marino return gen_lowpart (mode, new_rtx);
3785e4b17023SJohn Marino }
3786e4b17023SJohn Marino }
3787e4b17023SJohn Marino
3788e4b17023SJohn Marino /* Otherwise see if we already have a constant for the inner REG. */
3789e4b17023SJohn Marino if (REG_P (SUBREG_REG (x))
3790e4b17023SJohn Marino && (new_rtx = equiv_constant (SUBREG_REG (x))) != 0)
3791e4b17023SJohn Marino return simplify_subreg (mode, new_rtx, imode, SUBREG_BYTE (x));
3792e4b17023SJohn Marino
3793e4b17023SJohn Marino return 0;
3794e4b17023SJohn Marino }
3795e4b17023SJohn Marino
3796e4b17023SJohn Marino /* If X is a MEM, see if it is a constant-pool reference, or look it up in
3797e4b17023SJohn Marino the hash table in case its value was seen before. */
3798e4b17023SJohn Marino
3799e4b17023SJohn Marino if (MEM_P (x))
3800e4b17023SJohn Marino {
3801e4b17023SJohn Marino struct table_elt *elt;
3802e4b17023SJohn Marino
3803e4b17023SJohn Marino x = avoid_constant_pool_reference (x);
3804e4b17023SJohn Marino if (CONSTANT_P (x))
3805e4b17023SJohn Marino return x;
3806e4b17023SJohn Marino
3807e4b17023SJohn Marino elt = lookup (x, SAFE_HASH (x, GET_MODE (x)), GET_MODE (x));
3808e4b17023SJohn Marino if (elt == 0)
3809e4b17023SJohn Marino return 0;
3810e4b17023SJohn Marino
3811e4b17023SJohn Marino for (elt = elt->first_same_value; elt; elt = elt->next_same_value)
3812e4b17023SJohn Marino if (elt->is_const && CONSTANT_P (elt->exp))
3813e4b17023SJohn Marino return elt->exp;
3814e4b17023SJohn Marino }
3815e4b17023SJohn Marino
3816e4b17023SJohn Marino return 0;
3817e4b17023SJohn Marino }
3818e4b17023SJohn Marino
3819e4b17023SJohn Marino /* Given INSN, a jump insn, TAKEN indicates if we are following the
3820e4b17023SJohn Marino "taken" branch.
3821e4b17023SJohn Marino
3822e4b17023SJohn Marino In certain cases, this can cause us to add an equivalence. For example,
3823e4b17023SJohn Marino if we are following the taken case of
3824e4b17023SJohn Marino if (i == 2)
3825e4b17023SJohn Marino we can add the fact that `i' and '2' are now equivalent.
3826e4b17023SJohn Marino
3827e4b17023SJohn Marino In any case, we can record that this comparison was passed. If the same
3828e4b17023SJohn Marino comparison is seen later, we will know its value. */
3829e4b17023SJohn Marino
3830e4b17023SJohn Marino static void
record_jump_equiv(rtx insn,bool taken)3831e4b17023SJohn Marino record_jump_equiv (rtx insn, bool taken)
3832e4b17023SJohn Marino {
3833e4b17023SJohn Marino int cond_known_true;
3834e4b17023SJohn Marino rtx op0, op1;
3835e4b17023SJohn Marino rtx set;
3836e4b17023SJohn Marino enum machine_mode mode, mode0, mode1;
3837e4b17023SJohn Marino int reversed_nonequality = 0;
3838e4b17023SJohn Marino enum rtx_code code;
3839e4b17023SJohn Marino
3840e4b17023SJohn Marino /* Ensure this is the right kind of insn. */
3841e4b17023SJohn Marino gcc_assert (any_condjump_p (insn));
3842e4b17023SJohn Marino
3843e4b17023SJohn Marino set = pc_set (insn);
3844e4b17023SJohn Marino
3845e4b17023SJohn Marino /* See if this jump condition is known true or false. */
3846e4b17023SJohn Marino if (taken)
3847e4b17023SJohn Marino cond_known_true = (XEXP (SET_SRC (set), 2) == pc_rtx);
3848e4b17023SJohn Marino else
3849e4b17023SJohn Marino cond_known_true = (XEXP (SET_SRC (set), 1) == pc_rtx);
3850e4b17023SJohn Marino
3851e4b17023SJohn Marino /* Get the type of comparison being done and the operands being compared.
3852e4b17023SJohn Marino If we had to reverse a non-equality condition, record that fact so we
3853e4b17023SJohn Marino know that it isn't valid for floating-point. */
3854e4b17023SJohn Marino code = GET_CODE (XEXP (SET_SRC (set), 0));
3855e4b17023SJohn Marino op0 = fold_rtx (XEXP (XEXP (SET_SRC (set), 0), 0), insn);
3856e4b17023SJohn Marino op1 = fold_rtx (XEXP (XEXP (SET_SRC (set), 0), 1), insn);
3857e4b17023SJohn Marino
3858e4b17023SJohn Marino code = find_comparison_args (code, &op0, &op1, &mode0, &mode1);
3859e4b17023SJohn Marino if (! cond_known_true)
3860e4b17023SJohn Marino {
3861e4b17023SJohn Marino code = reversed_comparison_code_parts (code, op0, op1, insn);
3862e4b17023SJohn Marino
3863e4b17023SJohn Marino /* Don't remember if we can't find the inverse. */
3864e4b17023SJohn Marino if (code == UNKNOWN)
3865e4b17023SJohn Marino return;
3866e4b17023SJohn Marino }
3867e4b17023SJohn Marino
3868e4b17023SJohn Marino /* The mode is the mode of the non-constant. */
3869e4b17023SJohn Marino mode = mode0;
3870e4b17023SJohn Marino if (mode1 != VOIDmode)
3871e4b17023SJohn Marino mode = mode1;
3872e4b17023SJohn Marino
3873e4b17023SJohn Marino record_jump_cond (code, mode, op0, op1, reversed_nonequality);
3874e4b17023SJohn Marino }
3875e4b17023SJohn Marino
3876e4b17023SJohn Marino /* Yet another form of subreg creation. In this case, we want something in
3877e4b17023SJohn Marino MODE, and we should assume OP has MODE iff it is naturally modeless. */
3878e4b17023SJohn Marino
3879e4b17023SJohn Marino static rtx
record_jump_cond_subreg(enum machine_mode mode,rtx op)3880e4b17023SJohn Marino record_jump_cond_subreg (enum machine_mode mode, rtx op)
3881e4b17023SJohn Marino {
3882e4b17023SJohn Marino enum machine_mode op_mode = GET_MODE (op);
3883e4b17023SJohn Marino if (op_mode == mode || op_mode == VOIDmode)
3884e4b17023SJohn Marino return op;
3885e4b17023SJohn Marino return lowpart_subreg (mode, op, op_mode);
3886e4b17023SJohn Marino }
3887e4b17023SJohn Marino
3888e4b17023SJohn Marino /* We know that comparison CODE applied to OP0 and OP1 in MODE is true.
3889e4b17023SJohn Marino REVERSED_NONEQUALITY is nonzero if CODE had to be swapped.
3890e4b17023SJohn Marino Make any useful entries we can with that information. Called from
3891e4b17023SJohn Marino above function and called recursively. */
3892e4b17023SJohn Marino
3893e4b17023SJohn Marino static void
record_jump_cond(enum rtx_code code,enum machine_mode mode,rtx op0,rtx op1,int reversed_nonequality)3894e4b17023SJohn Marino record_jump_cond (enum rtx_code code, enum machine_mode mode, rtx op0,
3895e4b17023SJohn Marino rtx op1, int reversed_nonequality)
3896e4b17023SJohn Marino {
3897e4b17023SJohn Marino unsigned op0_hash, op1_hash;
3898e4b17023SJohn Marino int op0_in_memory, op1_in_memory;
3899e4b17023SJohn Marino struct table_elt *op0_elt, *op1_elt;
3900e4b17023SJohn Marino
3901e4b17023SJohn Marino /* If OP0 and OP1 are known equal, and either is a paradoxical SUBREG,
3902e4b17023SJohn Marino we know that they are also equal in the smaller mode (this is also
3903e4b17023SJohn Marino true for all smaller modes whether or not there is a SUBREG, but
3904e4b17023SJohn Marino is not worth testing for with no SUBREG). */
3905e4b17023SJohn Marino
3906e4b17023SJohn Marino /* Note that GET_MODE (op0) may not equal MODE. */
3907e4b17023SJohn Marino if (code == EQ && paradoxical_subreg_p (op0))
3908e4b17023SJohn Marino {
3909e4b17023SJohn Marino enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
3910e4b17023SJohn Marino rtx tem = record_jump_cond_subreg (inner_mode, op1);
3911e4b17023SJohn Marino if (tem)
3912e4b17023SJohn Marino record_jump_cond (code, mode, SUBREG_REG (op0), tem,
3913e4b17023SJohn Marino reversed_nonequality);
3914e4b17023SJohn Marino }
3915e4b17023SJohn Marino
3916e4b17023SJohn Marino if (code == EQ && paradoxical_subreg_p (op1))
3917e4b17023SJohn Marino {
3918e4b17023SJohn Marino enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
3919e4b17023SJohn Marino rtx tem = record_jump_cond_subreg (inner_mode, op0);
3920e4b17023SJohn Marino if (tem)
3921e4b17023SJohn Marino record_jump_cond (code, mode, SUBREG_REG (op1), tem,
3922e4b17023SJohn Marino reversed_nonequality);
3923e4b17023SJohn Marino }
3924e4b17023SJohn Marino
3925e4b17023SJohn Marino /* Similarly, if this is an NE comparison, and either is a SUBREG
3926e4b17023SJohn Marino making a smaller mode, we know the whole thing is also NE. */
3927e4b17023SJohn Marino
3928e4b17023SJohn Marino /* Note that GET_MODE (op0) may not equal MODE;
3929e4b17023SJohn Marino if we test MODE instead, we can get an infinite recursion
3930e4b17023SJohn Marino alternating between two modes each wider than MODE. */
3931e4b17023SJohn Marino
3932e4b17023SJohn Marino if (code == NE && GET_CODE (op0) == SUBREG
3933e4b17023SJohn Marino && subreg_lowpart_p (op0)
3934e4b17023SJohn Marino && (GET_MODE_SIZE (GET_MODE (op0))
3935e4b17023SJohn Marino < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
3936e4b17023SJohn Marino {
3937e4b17023SJohn Marino enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
3938e4b17023SJohn Marino rtx tem = record_jump_cond_subreg (inner_mode, op1);
3939e4b17023SJohn Marino if (tem)
3940e4b17023SJohn Marino record_jump_cond (code, mode, SUBREG_REG (op0), tem,
3941e4b17023SJohn Marino reversed_nonequality);
3942e4b17023SJohn Marino }
3943e4b17023SJohn Marino
3944e4b17023SJohn Marino if (code == NE && GET_CODE (op1) == SUBREG
3945e4b17023SJohn Marino && subreg_lowpart_p (op1)
3946e4b17023SJohn Marino && (GET_MODE_SIZE (GET_MODE (op1))
3947e4b17023SJohn Marino < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
3948e4b17023SJohn Marino {
3949e4b17023SJohn Marino enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
3950e4b17023SJohn Marino rtx tem = record_jump_cond_subreg (inner_mode, op0);
3951e4b17023SJohn Marino if (tem)
3952e4b17023SJohn Marino record_jump_cond (code, mode, SUBREG_REG (op1), tem,
3953e4b17023SJohn Marino reversed_nonequality);
3954e4b17023SJohn Marino }
3955e4b17023SJohn Marino
3956e4b17023SJohn Marino /* Hash both operands. */
3957e4b17023SJohn Marino
3958e4b17023SJohn Marino do_not_record = 0;
3959e4b17023SJohn Marino hash_arg_in_memory = 0;
3960e4b17023SJohn Marino op0_hash = HASH (op0, mode);
3961e4b17023SJohn Marino op0_in_memory = hash_arg_in_memory;
3962e4b17023SJohn Marino
3963e4b17023SJohn Marino if (do_not_record)
3964e4b17023SJohn Marino return;
3965e4b17023SJohn Marino
3966e4b17023SJohn Marino do_not_record = 0;
3967e4b17023SJohn Marino hash_arg_in_memory = 0;
3968e4b17023SJohn Marino op1_hash = HASH (op1, mode);
3969e4b17023SJohn Marino op1_in_memory = hash_arg_in_memory;
3970e4b17023SJohn Marino
3971e4b17023SJohn Marino if (do_not_record)
3972e4b17023SJohn Marino return;
3973e4b17023SJohn Marino
3974e4b17023SJohn Marino /* Look up both operands. */
3975e4b17023SJohn Marino op0_elt = lookup (op0, op0_hash, mode);
3976e4b17023SJohn Marino op1_elt = lookup (op1, op1_hash, mode);
3977e4b17023SJohn Marino
3978e4b17023SJohn Marino /* If both operands are already equivalent or if they are not in the
3979e4b17023SJohn Marino table but are identical, do nothing. */
3980e4b17023SJohn Marino if ((op0_elt != 0 && op1_elt != 0
3981e4b17023SJohn Marino && op0_elt->first_same_value == op1_elt->first_same_value)
3982e4b17023SJohn Marino || op0 == op1 || rtx_equal_p (op0, op1))
3983e4b17023SJohn Marino return;
3984e4b17023SJohn Marino
3985e4b17023SJohn Marino /* If we aren't setting two things equal all we can do is save this
3986e4b17023SJohn Marino comparison. Similarly if this is floating-point. In the latter
3987e4b17023SJohn Marino case, OP1 might be zero and both -0.0 and 0.0 are equal to it.
3988e4b17023SJohn Marino If we record the equality, we might inadvertently delete code
3989e4b17023SJohn Marino whose intent was to change -0 to +0. */
3990e4b17023SJohn Marino
3991e4b17023SJohn Marino if (code != EQ || FLOAT_MODE_P (GET_MODE (op0)))
3992e4b17023SJohn Marino {
3993e4b17023SJohn Marino struct qty_table_elem *ent;
3994e4b17023SJohn Marino int qty;
3995e4b17023SJohn Marino
3996e4b17023SJohn Marino /* If we reversed a floating-point comparison, if OP0 is not a
3997e4b17023SJohn Marino register, or if OP1 is neither a register or constant, we can't
3998e4b17023SJohn Marino do anything. */
3999e4b17023SJohn Marino
4000e4b17023SJohn Marino if (!REG_P (op1))
4001e4b17023SJohn Marino op1 = equiv_constant (op1);
4002e4b17023SJohn Marino
4003e4b17023SJohn Marino if ((reversed_nonequality && FLOAT_MODE_P (mode))
4004e4b17023SJohn Marino || !REG_P (op0) || op1 == 0)
4005e4b17023SJohn Marino return;
4006e4b17023SJohn Marino
4007e4b17023SJohn Marino /* Put OP0 in the hash table if it isn't already. This gives it a
4008e4b17023SJohn Marino new quantity number. */
4009e4b17023SJohn Marino if (op0_elt == 0)
4010e4b17023SJohn Marino {
4011e4b17023SJohn Marino if (insert_regs (op0, NULL, 0))
4012e4b17023SJohn Marino {
4013e4b17023SJohn Marino rehash_using_reg (op0);
4014e4b17023SJohn Marino op0_hash = HASH (op0, mode);
4015e4b17023SJohn Marino
4016e4b17023SJohn Marino /* If OP0 is contained in OP1, this changes its hash code
4017e4b17023SJohn Marino as well. Faster to rehash than to check, except
4018e4b17023SJohn Marino for the simple case of a constant. */
4019e4b17023SJohn Marino if (! CONSTANT_P (op1))
4020e4b17023SJohn Marino op1_hash = HASH (op1,mode);
4021e4b17023SJohn Marino }
4022e4b17023SJohn Marino
4023e4b17023SJohn Marino op0_elt = insert (op0, NULL, op0_hash, mode);
4024e4b17023SJohn Marino op0_elt->in_memory = op0_in_memory;
4025e4b17023SJohn Marino }
4026e4b17023SJohn Marino
4027e4b17023SJohn Marino qty = REG_QTY (REGNO (op0));
4028e4b17023SJohn Marino ent = &qty_table[qty];
4029e4b17023SJohn Marino
4030e4b17023SJohn Marino ent->comparison_code = code;
4031e4b17023SJohn Marino if (REG_P (op1))
4032e4b17023SJohn Marino {
4033e4b17023SJohn Marino /* Look it up again--in case op0 and op1 are the same. */
4034e4b17023SJohn Marino op1_elt = lookup (op1, op1_hash, mode);
4035e4b17023SJohn Marino
4036e4b17023SJohn Marino /* Put OP1 in the hash table so it gets a new quantity number. */
4037e4b17023SJohn Marino if (op1_elt == 0)
4038e4b17023SJohn Marino {
4039e4b17023SJohn Marino if (insert_regs (op1, NULL, 0))
4040e4b17023SJohn Marino {
4041e4b17023SJohn Marino rehash_using_reg (op1);
4042e4b17023SJohn Marino op1_hash = HASH (op1, mode);
4043e4b17023SJohn Marino }
4044e4b17023SJohn Marino
4045e4b17023SJohn Marino op1_elt = insert (op1, NULL, op1_hash, mode);
4046e4b17023SJohn Marino op1_elt->in_memory = op1_in_memory;
4047e4b17023SJohn Marino }
4048e4b17023SJohn Marino
4049e4b17023SJohn Marino ent->comparison_const = NULL_RTX;
4050e4b17023SJohn Marino ent->comparison_qty = REG_QTY (REGNO (op1));
4051e4b17023SJohn Marino }
4052e4b17023SJohn Marino else
4053e4b17023SJohn Marino {
4054e4b17023SJohn Marino ent->comparison_const = op1;
4055e4b17023SJohn Marino ent->comparison_qty = -1;
4056e4b17023SJohn Marino }
4057e4b17023SJohn Marino
4058e4b17023SJohn Marino return;
4059e4b17023SJohn Marino }
4060e4b17023SJohn Marino
4061e4b17023SJohn Marino /* If either side is still missing an equivalence, make it now,
4062e4b17023SJohn Marino then merge the equivalences. */
4063e4b17023SJohn Marino
4064e4b17023SJohn Marino if (op0_elt == 0)
4065e4b17023SJohn Marino {
4066e4b17023SJohn Marino if (insert_regs (op0, NULL, 0))
4067e4b17023SJohn Marino {
4068e4b17023SJohn Marino rehash_using_reg (op0);
4069e4b17023SJohn Marino op0_hash = HASH (op0, mode);
4070e4b17023SJohn Marino }
4071e4b17023SJohn Marino
4072e4b17023SJohn Marino op0_elt = insert (op0, NULL, op0_hash, mode);
4073e4b17023SJohn Marino op0_elt->in_memory = op0_in_memory;
4074e4b17023SJohn Marino }
4075e4b17023SJohn Marino
4076e4b17023SJohn Marino if (op1_elt == 0)
4077e4b17023SJohn Marino {
4078e4b17023SJohn Marino if (insert_regs (op1, NULL, 0))
4079e4b17023SJohn Marino {
4080e4b17023SJohn Marino rehash_using_reg (op1);
4081e4b17023SJohn Marino op1_hash = HASH (op1, mode);
4082e4b17023SJohn Marino }
4083e4b17023SJohn Marino
4084e4b17023SJohn Marino op1_elt = insert (op1, NULL, op1_hash, mode);
4085e4b17023SJohn Marino op1_elt->in_memory = op1_in_memory;
4086e4b17023SJohn Marino }
4087e4b17023SJohn Marino
4088e4b17023SJohn Marino merge_equiv_classes (op0_elt, op1_elt);
4089e4b17023SJohn Marino }
4090e4b17023SJohn Marino
4091e4b17023SJohn Marino /* CSE processing for one instruction.
4092e4b17023SJohn Marino First simplify sources and addresses of all assignments
4093e4b17023SJohn Marino in the instruction, using previously-computed equivalents values.
4094e4b17023SJohn Marino Then install the new sources and destinations in the table
4095e4b17023SJohn Marino of available values. */
4096e4b17023SJohn Marino
4097e4b17023SJohn Marino /* Data on one SET contained in the instruction. */
4098e4b17023SJohn Marino
4099e4b17023SJohn Marino struct set
4100e4b17023SJohn Marino {
4101e4b17023SJohn Marino /* The SET rtx itself. */
4102e4b17023SJohn Marino rtx rtl;
4103e4b17023SJohn Marino /* The SET_SRC of the rtx (the original value, if it is changing). */
4104e4b17023SJohn Marino rtx src;
4105e4b17023SJohn Marino /* The hash-table element for the SET_SRC of the SET. */
4106e4b17023SJohn Marino struct table_elt *src_elt;
4107e4b17023SJohn Marino /* Hash value for the SET_SRC. */
4108e4b17023SJohn Marino unsigned src_hash;
4109e4b17023SJohn Marino /* Hash value for the SET_DEST. */
4110e4b17023SJohn Marino unsigned dest_hash;
4111e4b17023SJohn Marino /* The SET_DEST, with SUBREG, etc., stripped. */
4112e4b17023SJohn Marino rtx inner_dest;
4113e4b17023SJohn Marino /* Nonzero if the SET_SRC is in memory. */
4114e4b17023SJohn Marino char src_in_memory;
4115e4b17023SJohn Marino /* Nonzero if the SET_SRC contains something
4116e4b17023SJohn Marino whose value cannot be predicted and understood. */
4117e4b17023SJohn Marino char src_volatile;
4118e4b17023SJohn Marino /* Original machine mode, in case it becomes a CONST_INT.
4119e4b17023SJohn Marino The size of this field should match the size of the mode
4120e4b17023SJohn Marino field of struct rtx_def (see rtl.h). */
4121e4b17023SJohn Marino ENUM_BITFIELD(machine_mode) mode : 8;
4122e4b17023SJohn Marino /* A constant equivalent for SET_SRC, if any. */
4123e4b17023SJohn Marino rtx src_const;
4124e4b17023SJohn Marino /* Hash value of constant equivalent for SET_SRC. */
4125e4b17023SJohn Marino unsigned src_const_hash;
4126e4b17023SJohn Marino /* Table entry for constant equivalent for SET_SRC, if any. */
4127e4b17023SJohn Marino struct table_elt *src_const_elt;
4128e4b17023SJohn Marino /* Table entry for the destination address. */
4129e4b17023SJohn Marino struct table_elt *dest_addr_elt;
4130e4b17023SJohn Marino };
4131e4b17023SJohn Marino
4132e4b17023SJohn Marino static void
cse_insn(rtx insn)4133e4b17023SJohn Marino cse_insn (rtx insn)
4134e4b17023SJohn Marino {
4135e4b17023SJohn Marino rtx x = PATTERN (insn);
4136e4b17023SJohn Marino int i;
4137e4b17023SJohn Marino rtx tem;
4138e4b17023SJohn Marino int n_sets = 0;
4139e4b17023SJohn Marino
4140e4b17023SJohn Marino rtx src_eqv = 0;
4141e4b17023SJohn Marino struct table_elt *src_eqv_elt = 0;
4142e4b17023SJohn Marino int src_eqv_volatile = 0;
4143e4b17023SJohn Marino int src_eqv_in_memory = 0;
4144e4b17023SJohn Marino unsigned src_eqv_hash = 0;
4145e4b17023SJohn Marino
4146e4b17023SJohn Marino struct set *sets = (struct set *) 0;
4147e4b17023SJohn Marino
4148e4b17023SJohn Marino this_insn = insn;
4149e4b17023SJohn Marino #ifdef HAVE_cc0
4150e4b17023SJohn Marino /* Records what this insn does to set CC0. */
4151e4b17023SJohn Marino this_insn_cc0 = 0;
4152e4b17023SJohn Marino this_insn_cc0_mode = VOIDmode;
4153e4b17023SJohn Marino #endif
4154e4b17023SJohn Marino
4155e4b17023SJohn Marino /* Find all the SETs and CLOBBERs in this instruction.
4156e4b17023SJohn Marino Record all the SETs in the array `set' and count them.
4157e4b17023SJohn Marino Also determine whether there is a CLOBBER that invalidates
4158e4b17023SJohn Marino all memory references, or all references at varying addresses. */
4159e4b17023SJohn Marino
4160e4b17023SJohn Marino if (CALL_P (insn))
4161e4b17023SJohn Marino {
4162e4b17023SJohn Marino for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4163e4b17023SJohn Marino {
4164e4b17023SJohn Marino if (GET_CODE (XEXP (tem, 0)) == CLOBBER)
4165e4b17023SJohn Marino invalidate (SET_DEST (XEXP (tem, 0)), VOIDmode);
4166e4b17023SJohn Marino XEXP (tem, 0) = canon_reg (XEXP (tem, 0), insn);
4167e4b17023SJohn Marino }
4168e4b17023SJohn Marino }
4169e4b17023SJohn Marino
4170e4b17023SJohn Marino if (GET_CODE (x) == SET)
4171e4b17023SJohn Marino {
4172e4b17023SJohn Marino sets = XALLOCA (struct set);
4173e4b17023SJohn Marino sets[0].rtl = x;
4174e4b17023SJohn Marino
4175e4b17023SJohn Marino /* Ignore SETs that are unconditional jumps.
4176e4b17023SJohn Marino They never need cse processing, so this does not hurt.
4177e4b17023SJohn Marino The reason is not efficiency but rather
4178e4b17023SJohn Marino so that we can test at the end for instructions
4179e4b17023SJohn Marino that have been simplified to unconditional jumps
4180e4b17023SJohn Marino and not be misled by unchanged instructions
4181e4b17023SJohn Marino that were unconditional jumps to begin with. */
4182e4b17023SJohn Marino if (SET_DEST (x) == pc_rtx
4183e4b17023SJohn Marino && GET_CODE (SET_SRC (x)) == LABEL_REF)
4184e4b17023SJohn Marino ;
4185e4b17023SJohn Marino
4186e4b17023SJohn Marino /* Don't count call-insns, (set (reg 0) (call ...)), as a set.
4187e4b17023SJohn Marino The hard function value register is used only once, to copy to
4188e4b17023SJohn Marino someplace else, so it isn't worth cse'ing (and on 80386 is unsafe)!
4189e4b17023SJohn Marino Ensure we invalidate the destination register. On the 80386 no
4190e4b17023SJohn Marino other code would invalidate it since it is a fixed_reg.
4191e4b17023SJohn Marino We need not check the return of apply_change_group; see canon_reg. */
4192e4b17023SJohn Marino
4193e4b17023SJohn Marino else if (GET_CODE (SET_SRC (x)) == CALL)
4194e4b17023SJohn Marino {
4195e4b17023SJohn Marino canon_reg (SET_SRC (x), insn);
4196e4b17023SJohn Marino apply_change_group ();
4197e4b17023SJohn Marino fold_rtx (SET_SRC (x), insn);
4198e4b17023SJohn Marino invalidate (SET_DEST (x), VOIDmode);
4199e4b17023SJohn Marino }
4200e4b17023SJohn Marino else
4201e4b17023SJohn Marino n_sets = 1;
4202e4b17023SJohn Marino }
4203e4b17023SJohn Marino else if (GET_CODE (x) == PARALLEL)
4204e4b17023SJohn Marino {
4205e4b17023SJohn Marino int lim = XVECLEN (x, 0);
4206e4b17023SJohn Marino
4207e4b17023SJohn Marino sets = XALLOCAVEC (struct set, lim);
4208e4b17023SJohn Marino
4209e4b17023SJohn Marino /* Find all regs explicitly clobbered in this insn,
4210e4b17023SJohn Marino and ensure they are not replaced with any other regs
4211e4b17023SJohn Marino elsewhere in this insn.
4212e4b17023SJohn Marino When a reg that is clobbered is also used for input,
4213e4b17023SJohn Marino we should presume that that is for a reason,
4214e4b17023SJohn Marino and we should not substitute some other register
4215e4b17023SJohn Marino which is not supposed to be clobbered.
4216e4b17023SJohn Marino Therefore, this loop cannot be merged into the one below
4217e4b17023SJohn Marino because a CALL may precede a CLOBBER and refer to the
4218e4b17023SJohn Marino value clobbered. We must not let a canonicalization do
4219e4b17023SJohn Marino anything in that case. */
4220e4b17023SJohn Marino for (i = 0; i < lim; i++)
4221e4b17023SJohn Marino {
4222e4b17023SJohn Marino rtx y = XVECEXP (x, 0, i);
4223e4b17023SJohn Marino if (GET_CODE (y) == CLOBBER)
4224e4b17023SJohn Marino {
4225e4b17023SJohn Marino rtx clobbered = XEXP (y, 0);
4226e4b17023SJohn Marino
4227e4b17023SJohn Marino if (REG_P (clobbered)
4228e4b17023SJohn Marino || GET_CODE (clobbered) == SUBREG)
4229e4b17023SJohn Marino invalidate (clobbered, VOIDmode);
4230e4b17023SJohn Marino else if (GET_CODE (clobbered) == STRICT_LOW_PART
4231e4b17023SJohn Marino || GET_CODE (clobbered) == ZERO_EXTRACT)
4232e4b17023SJohn Marino invalidate (XEXP (clobbered, 0), GET_MODE (clobbered));
4233e4b17023SJohn Marino }
4234e4b17023SJohn Marino }
4235e4b17023SJohn Marino
4236e4b17023SJohn Marino for (i = 0; i < lim; i++)
4237e4b17023SJohn Marino {
4238e4b17023SJohn Marino rtx y = XVECEXP (x, 0, i);
4239e4b17023SJohn Marino if (GET_CODE (y) == SET)
4240e4b17023SJohn Marino {
4241e4b17023SJohn Marino /* As above, we ignore unconditional jumps and call-insns and
4242e4b17023SJohn Marino ignore the result of apply_change_group. */
4243e4b17023SJohn Marino if (GET_CODE (SET_SRC (y)) == CALL)
4244e4b17023SJohn Marino {
4245e4b17023SJohn Marino canon_reg (SET_SRC (y), insn);
4246e4b17023SJohn Marino apply_change_group ();
4247e4b17023SJohn Marino fold_rtx (SET_SRC (y), insn);
4248e4b17023SJohn Marino invalidate (SET_DEST (y), VOIDmode);
4249e4b17023SJohn Marino }
4250e4b17023SJohn Marino else if (SET_DEST (y) == pc_rtx
4251e4b17023SJohn Marino && GET_CODE (SET_SRC (y)) == LABEL_REF)
4252e4b17023SJohn Marino ;
4253e4b17023SJohn Marino else
4254e4b17023SJohn Marino sets[n_sets++].rtl = y;
4255e4b17023SJohn Marino }
4256e4b17023SJohn Marino else if (GET_CODE (y) == CLOBBER)
4257e4b17023SJohn Marino {
4258e4b17023SJohn Marino /* If we clobber memory, canon the address.
4259e4b17023SJohn Marino This does nothing when a register is clobbered
4260e4b17023SJohn Marino because we have already invalidated the reg. */
4261e4b17023SJohn Marino if (MEM_P (XEXP (y, 0)))
4262e4b17023SJohn Marino canon_reg (XEXP (y, 0), insn);
4263e4b17023SJohn Marino }
4264e4b17023SJohn Marino else if (GET_CODE (y) == USE
4265e4b17023SJohn Marino && ! (REG_P (XEXP (y, 0))
4266e4b17023SJohn Marino && REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER))
4267e4b17023SJohn Marino canon_reg (y, insn);
4268e4b17023SJohn Marino else if (GET_CODE (y) == CALL)
4269e4b17023SJohn Marino {
4270e4b17023SJohn Marino /* The result of apply_change_group can be ignored; see
4271e4b17023SJohn Marino canon_reg. */
4272e4b17023SJohn Marino canon_reg (y, insn);
4273e4b17023SJohn Marino apply_change_group ();
4274e4b17023SJohn Marino fold_rtx (y, insn);
4275e4b17023SJohn Marino }
4276e4b17023SJohn Marino }
4277e4b17023SJohn Marino }
4278e4b17023SJohn Marino else if (GET_CODE (x) == CLOBBER)
4279e4b17023SJohn Marino {
4280e4b17023SJohn Marino if (MEM_P (XEXP (x, 0)))
4281e4b17023SJohn Marino canon_reg (XEXP (x, 0), insn);
4282e4b17023SJohn Marino }
4283e4b17023SJohn Marino /* Canonicalize a USE of a pseudo register or memory location. */
4284e4b17023SJohn Marino else if (GET_CODE (x) == USE
4285e4b17023SJohn Marino && ! (REG_P (XEXP (x, 0))
4286e4b17023SJohn Marino && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER))
4287e4b17023SJohn Marino canon_reg (x, insn);
4288e4b17023SJohn Marino else if (GET_CODE (x) == ASM_OPERANDS)
4289e4b17023SJohn Marino {
4290e4b17023SJohn Marino for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
4291e4b17023SJohn Marino {
4292e4b17023SJohn Marino rtx input = ASM_OPERANDS_INPUT (x, i);
4293e4b17023SJohn Marino if (!(REG_P (input) && REGNO (input) < FIRST_PSEUDO_REGISTER))
4294e4b17023SJohn Marino {
4295e4b17023SJohn Marino input = canon_reg (input, insn);
4296e4b17023SJohn Marino validate_change (insn, &ASM_OPERANDS_INPUT (x, i), input, 1);
4297e4b17023SJohn Marino }
4298e4b17023SJohn Marino }
4299e4b17023SJohn Marino }
4300e4b17023SJohn Marino else if (GET_CODE (x) == CALL)
4301e4b17023SJohn Marino {
4302e4b17023SJohn Marino /* The result of apply_change_group can be ignored; see canon_reg. */
4303e4b17023SJohn Marino canon_reg (x, insn);
4304e4b17023SJohn Marino apply_change_group ();
4305e4b17023SJohn Marino fold_rtx (x, insn);
4306e4b17023SJohn Marino }
4307e4b17023SJohn Marino else if (DEBUG_INSN_P (insn))
4308e4b17023SJohn Marino canon_reg (PATTERN (insn), insn);
4309e4b17023SJohn Marino
4310e4b17023SJohn Marino /* Store the equivalent value in SRC_EQV, if different, or if the DEST
4311e4b17023SJohn Marino is a STRICT_LOW_PART. The latter condition is necessary because SRC_EQV
4312e4b17023SJohn Marino is handled specially for this case, and if it isn't set, then there will
4313e4b17023SJohn Marino be no equivalence for the destination. */
4314e4b17023SJohn Marino if (n_sets == 1 && REG_NOTES (insn) != 0
4315e4b17023SJohn Marino && (tem = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0
4316e4b17023SJohn Marino && (! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))
4317e4b17023SJohn Marino || GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART))
4318e4b17023SJohn Marino {
4319e4b17023SJohn Marino /* The result of apply_change_group can be ignored; see canon_reg. */
4320e4b17023SJohn Marino canon_reg (XEXP (tem, 0), insn);
4321e4b17023SJohn Marino apply_change_group ();
4322e4b17023SJohn Marino src_eqv = fold_rtx (XEXP (tem, 0), insn);
4323e4b17023SJohn Marino XEXP (tem, 0) = copy_rtx (src_eqv);
4324e4b17023SJohn Marino df_notes_rescan (insn);
4325e4b17023SJohn Marino }
4326e4b17023SJohn Marino
4327e4b17023SJohn Marino /* Canonicalize sources and addresses of destinations.
4328e4b17023SJohn Marino We do this in a separate pass to avoid problems when a MATCH_DUP is
4329e4b17023SJohn Marino present in the insn pattern. In that case, we want to ensure that
4330e4b17023SJohn Marino we don't break the duplicate nature of the pattern. So we will replace
4331e4b17023SJohn Marino both operands at the same time. Otherwise, we would fail to find an
4332e4b17023SJohn Marino equivalent substitution in the loop calling validate_change below.
4333e4b17023SJohn Marino
4334e4b17023SJohn Marino We used to suppress canonicalization of DEST if it appears in SRC,
4335e4b17023SJohn Marino but we don't do this any more. */
4336e4b17023SJohn Marino
4337e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
4338e4b17023SJohn Marino {
4339e4b17023SJohn Marino rtx dest = SET_DEST (sets[i].rtl);
4340e4b17023SJohn Marino rtx src = SET_SRC (sets[i].rtl);
4341e4b17023SJohn Marino rtx new_rtx = canon_reg (src, insn);
4342e4b17023SJohn Marino
4343e4b17023SJohn Marino validate_change (insn, &SET_SRC (sets[i].rtl), new_rtx, 1);
4344e4b17023SJohn Marino
4345e4b17023SJohn Marino if (GET_CODE (dest) == ZERO_EXTRACT)
4346e4b17023SJohn Marino {
4347e4b17023SJohn Marino validate_change (insn, &XEXP (dest, 1),
4348e4b17023SJohn Marino canon_reg (XEXP (dest, 1), insn), 1);
4349e4b17023SJohn Marino validate_change (insn, &XEXP (dest, 2),
4350e4b17023SJohn Marino canon_reg (XEXP (dest, 2), insn), 1);
4351e4b17023SJohn Marino }
4352e4b17023SJohn Marino
4353e4b17023SJohn Marino while (GET_CODE (dest) == SUBREG
4354e4b17023SJohn Marino || GET_CODE (dest) == ZERO_EXTRACT
4355e4b17023SJohn Marino || GET_CODE (dest) == STRICT_LOW_PART)
4356e4b17023SJohn Marino dest = XEXP (dest, 0);
4357e4b17023SJohn Marino
4358e4b17023SJohn Marino if (MEM_P (dest))
4359e4b17023SJohn Marino canon_reg (dest, insn);
4360e4b17023SJohn Marino }
4361e4b17023SJohn Marino
4362e4b17023SJohn Marino /* Now that we have done all the replacements, we can apply the change
4363e4b17023SJohn Marino group and see if they all work. Note that this will cause some
4364e4b17023SJohn Marino canonicalizations that would have worked individually not to be applied
4365e4b17023SJohn Marino because some other canonicalization didn't work, but this should not
4366e4b17023SJohn Marino occur often.
4367e4b17023SJohn Marino
4368e4b17023SJohn Marino The result of apply_change_group can be ignored; see canon_reg. */
4369e4b17023SJohn Marino
4370e4b17023SJohn Marino apply_change_group ();
4371e4b17023SJohn Marino
4372e4b17023SJohn Marino /* Set sets[i].src_elt to the class each source belongs to.
4373e4b17023SJohn Marino Detect assignments from or to volatile things
4374e4b17023SJohn Marino and set set[i] to zero so they will be ignored
4375e4b17023SJohn Marino in the rest of this function.
4376e4b17023SJohn Marino
4377e4b17023SJohn Marino Nothing in this loop changes the hash table or the register chains. */
4378e4b17023SJohn Marino
4379e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
4380e4b17023SJohn Marino {
4381e4b17023SJohn Marino bool repeat = false;
4382e4b17023SJohn Marino rtx src, dest;
4383e4b17023SJohn Marino rtx src_folded;
4384e4b17023SJohn Marino struct table_elt *elt = 0, *p;
4385e4b17023SJohn Marino enum machine_mode mode;
4386e4b17023SJohn Marino rtx src_eqv_here;
4387e4b17023SJohn Marino rtx src_const = 0;
4388e4b17023SJohn Marino rtx src_related = 0;
4389e4b17023SJohn Marino bool src_related_is_const_anchor = false;
4390e4b17023SJohn Marino struct table_elt *src_const_elt = 0;
4391e4b17023SJohn Marino int src_cost = MAX_COST;
4392e4b17023SJohn Marino int src_eqv_cost = MAX_COST;
4393e4b17023SJohn Marino int src_folded_cost = MAX_COST;
4394e4b17023SJohn Marino int src_related_cost = MAX_COST;
4395e4b17023SJohn Marino int src_elt_cost = MAX_COST;
4396e4b17023SJohn Marino int src_regcost = MAX_COST;
4397e4b17023SJohn Marino int src_eqv_regcost = MAX_COST;
4398e4b17023SJohn Marino int src_folded_regcost = MAX_COST;
4399e4b17023SJohn Marino int src_related_regcost = MAX_COST;
4400e4b17023SJohn Marino int src_elt_regcost = MAX_COST;
4401e4b17023SJohn Marino /* Set nonzero if we need to call force_const_mem on with the
4402e4b17023SJohn Marino contents of src_folded before using it. */
4403e4b17023SJohn Marino int src_folded_force_flag = 0;
4404e4b17023SJohn Marino
4405e4b17023SJohn Marino dest = SET_DEST (sets[i].rtl);
4406e4b17023SJohn Marino src = SET_SRC (sets[i].rtl);
4407e4b17023SJohn Marino
4408e4b17023SJohn Marino /* If SRC is a constant that has no machine mode,
4409e4b17023SJohn Marino hash it with the destination's machine mode.
4410e4b17023SJohn Marino This way we can keep different modes separate. */
4411e4b17023SJohn Marino
4412e4b17023SJohn Marino mode = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
4413e4b17023SJohn Marino sets[i].mode = mode;
4414e4b17023SJohn Marino
4415e4b17023SJohn Marino if (src_eqv)
4416e4b17023SJohn Marino {
4417e4b17023SJohn Marino enum machine_mode eqvmode = mode;
4418e4b17023SJohn Marino if (GET_CODE (dest) == STRICT_LOW_PART)
4419e4b17023SJohn Marino eqvmode = GET_MODE (SUBREG_REG (XEXP (dest, 0)));
4420e4b17023SJohn Marino do_not_record = 0;
4421e4b17023SJohn Marino hash_arg_in_memory = 0;
4422e4b17023SJohn Marino src_eqv_hash = HASH (src_eqv, eqvmode);
4423e4b17023SJohn Marino
4424e4b17023SJohn Marino /* Find the equivalence class for the equivalent expression. */
4425e4b17023SJohn Marino
4426e4b17023SJohn Marino if (!do_not_record)
4427e4b17023SJohn Marino src_eqv_elt = lookup (src_eqv, src_eqv_hash, eqvmode);
4428e4b17023SJohn Marino
4429e4b17023SJohn Marino src_eqv_volatile = do_not_record;
4430e4b17023SJohn Marino src_eqv_in_memory = hash_arg_in_memory;
4431e4b17023SJohn Marino }
4432e4b17023SJohn Marino
4433e4b17023SJohn Marino /* If this is a STRICT_LOW_PART assignment, src_eqv corresponds to the
4434e4b17023SJohn Marino value of the INNER register, not the destination. So it is not
4435e4b17023SJohn Marino a valid substitution for the source. But save it for later. */
4436e4b17023SJohn Marino if (GET_CODE (dest) == STRICT_LOW_PART)
4437e4b17023SJohn Marino src_eqv_here = 0;
4438e4b17023SJohn Marino else
4439e4b17023SJohn Marino src_eqv_here = src_eqv;
4440e4b17023SJohn Marino
4441e4b17023SJohn Marino /* Simplify and foldable subexpressions in SRC. Then get the fully-
4442e4b17023SJohn Marino simplified result, which may not necessarily be valid. */
4443e4b17023SJohn Marino src_folded = fold_rtx (src, insn);
4444e4b17023SJohn Marino
4445e4b17023SJohn Marino #if 0
4446e4b17023SJohn Marino /* ??? This caused bad code to be generated for the m68k port with -O2.
4447e4b17023SJohn Marino Suppose src is (CONST_INT -1), and that after truncation src_folded
4448e4b17023SJohn Marino is (CONST_INT 3). Suppose src_folded is then used for src_const.
4449e4b17023SJohn Marino At the end we will add src and src_const to the same equivalence
4450e4b17023SJohn Marino class. We now have 3 and -1 on the same equivalence class. This
4451e4b17023SJohn Marino causes later instructions to be mis-optimized. */
4452e4b17023SJohn Marino /* If storing a constant in a bitfield, pre-truncate the constant
4453e4b17023SJohn Marino so we will be able to record it later. */
4454e4b17023SJohn Marino if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT)
4455e4b17023SJohn Marino {
4456e4b17023SJohn Marino rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
4457e4b17023SJohn Marino
4458e4b17023SJohn Marino if (CONST_INT_P (src)
4459e4b17023SJohn Marino && CONST_INT_P (width)
4460e4b17023SJohn Marino && INTVAL (width) < HOST_BITS_PER_WIDE_INT
4461e4b17023SJohn Marino && (INTVAL (src) & ((HOST_WIDE_INT) (-1) << INTVAL (width))))
4462e4b17023SJohn Marino src_folded
4463e4b17023SJohn Marino = GEN_INT (INTVAL (src) & (((HOST_WIDE_INT) 1
4464e4b17023SJohn Marino << INTVAL (width)) - 1));
4465e4b17023SJohn Marino }
4466e4b17023SJohn Marino #endif
4467e4b17023SJohn Marino
4468e4b17023SJohn Marino /* Compute SRC's hash code, and also notice if it
4469e4b17023SJohn Marino should not be recorded at all. In that case,
4470e4b17023SJohn Marino prevent any further processing of this assignment. */
4471e4b17023SJohn Marino do_not_record = 0;
4472e4b17023SJohn Marino hash_arg_in_memory = 0;
4473e4b17023SJohn Marino
4474e4b17023SJohn Marino sets[i].src = src;
4475e4b17023SJohn Marino sets[i].src_hash = HASH (src, mode);
4476e4b17023SJohn Marino sets[i].src_volatile = do_not_record;
4477e4b17023SJohn Marino sets[i].src_in_memory = hash_arg_in_memory;
4478e4b17023SJohn Marino
4479e4b17023SJohn Marino /* If SRC is a MEM, there is a REG_EQUIV note for SRC, and DEST is
4480e4b17023SJohn Marino a pseudo, do not record SRC. Using SRC as a replacement for
4481e4b17023SJohn Marino anything else will be incorrect in that situation. Note that
4482e4b17023SJohn Marino this usually occurs only for stack slots, in which case all the
4483e4b17023SJohn Marino RTL would be referring to SRC, so we don't lose any optimization
4484e4b17023SJohn Marino opportunities by not having SRC in the hash table. */
4485e4b17023SJohn Marino
4486e4b17023SJohn Marino if (MEM_P (src)
4487e4b17023SJohn Marino && find_reg_note (insn, REG_EQUIV, NULL_RTX) != 0
4488e4b17023SJohn Marino && REG_P (dest)
4489e4b17023SJohn Marino && REGNO (dest) >= FIRST_PSEUDO_REGISTER)
4490e4b17023SJohn Marino sets[i].src_volatile = 1;
4491e4b17023SJohn Marino
4492e4b17023SJohn Marino #if 0
4493e4b17023SJohn Marino /* It is no longer clear why we used to do this, but it doesn't
4494e4b17023SJohn Marino appear to still be needed. So let's try without it since this
4495e4b17023SJohn Marino code hurts cse'ing widened ops. */
4496e4b17023SJohn Marino /* If source is a paradoxical subreg (such as QI treated as an SI),
4497e4b17023SJohn Marino treat it as volatile. It may do the work of an SI in one context
4498e4b17023SJohn Marino where the extra bits are not being used, but cannot replace an SI
4499e4b17023SJohn Marino in general. */
4500e4b17023SJohn Marino if (paradoxical_subreg_p (src))
4501e4b17023SJohn Marino sets[i].src_volatile = 1;
4502e4b17023SJohn Marino #endif
4503e4b17023SJohn Marino
4504e4b17023SJohn Marino /* Locate all possible equivalent forms for SRC. Try to replace
4505e4b17023SJohn Marino SRC in the insn with each cheaper equivalent.
4506e4b17023SJohn Marino
4507e4b17023SJohn Marino We have the following types of equivalents: SRC itself, a folded
4508e4b17023SJohn Marino version, a value given in a REG_EQUAL note, or a value related
4509e4b17023SJohn Marino to a constant.
4510e4b17023SJohn Marino
4511e4b17023SJohn Marino Each of these equivalents may be part of an additional class
4512e4b17023SJohn Marino of equivalents (if more than one is in the table, they must be in
4513e4b17023SJohn Marino the same class; we check for this).
4514e4b17023SJohn Marino
4515e4b17023SJohn Marino If the source is volatile, we don't do any table lookups.
4516e4b17023SJohn Marino
4517e4b17023SJohn Marino We note any constant equivalent for possible later use in a
4518e4b17023SJohn Marino REG_NOTE. */
4519e4b17023SJohn Marino
4520e4b17023SJohn Marino if (!sets[i].src_volatile)
4521e4b17023SJohn Marino elt = lookup (src, sets[i].src_hash, mode);
4522e4b17023SJohn Marino
4523e4b17023SJohn Marino sets[i].src_elt = elt;
4524e4b17023SJohn Marino
4525e4b17023SJohn Marino if (elt && src_eqv_here && src_eqv_elt)
4526e4b17023SJohn Marino {
4527e4b17023SJohn Marino if (elt->first_same_value != src_eqv_elt->first_same_value)
4528e4b17023SJohn Marino {
4529e4b17023SJohn Marino /* The REG_EQUAL is indicating that two formerly distinct
4530e4b17023SJohn Marino classes are now equivalent. So merge them. */
4531e4b17023SJohn Marino merge_equiv_classes (elt, src_eqv_elt);
4532e4b17023SJohn Marino src_eqv_hash = HASH (src_eqv, elt->mode);
4533e4b17023SJohn Marino src_eqv_elt = lookup (src_eqv, src_eqv_hash, elt->mode);
4534e4b17023SJohn Marino }
4535e4b17023SJohn Marino
4536e4b17023SJohn Marino src_eqv_here = 0;
4537e4b17023SJohn Marino }
4538e4b17023SJohn Marino
4539e4b17023SJohn Marino else if (src_eqv_elt)
4540e4b17023SJohn Marino elt = src_eqv_elt;
4541e4b17023SJohn Marino
4542e4b17023SJohn Marino /* Try to find a constant somewhere and record it in `src_const'.
4543e4b17023SJohn Marino Record its table element, if any, in `src_const_elt'. Look in
4544e4b17023SJohn Marino any known equivalences first. (If the constant is not in the
4545e4b17023SJohn Marino table, also set `sets[i].src_const_hash'). */
4546e4b17023SJohn Marino if (elt)
4547e4b17023SJohn Marino for (p = elt->first_same_value; p; p = p->next_same_value)
4548e4b17023SJohn Marino if (p->is_const)
4549e4b17023SJohn Marino {
4550e4b17023SJohn Marino src_const = p->exp;
4551e4b17023SJohn Marino src_const_elt = elt;
4552e4b17023SJohn Marino break;
4553e4b17023SJohn Marino }
4554e4b17023SJohn Marino
4555e4b17023SJohn Marino if (src_const == 0
4556e4b17023SJohn Marino && (CONSTANT_P (src_folded)
4557e4b17023SJohn Marino /* Consider (minus (label_ref L1) (label_ref L2)) as
4558e4b17023SJohn Marino "constant" here so we will record it. This allows us
4559e4b17023SJohn Marino to fold switch statements when an ADDR_DIFF_VEC is used. */
4560e4b17023SJohn Marino || (GET_CODE (src_folded) == MINUS
4561e4b17023SJohn Marino && GET_CODE (XEXP (src_folded, 0)) == LABEL_REF
4562e4b17023SJohn Marino && GET_CODE (XEXP (src_folded, 1)) == LABEL_REF)))
4563e4b17023SJohn Marino src_const = src_folded, src_const_elt = elt;
4564e4b17023SJohn Marino else if (src_const == 0 && src_eqv_here && CONSTANT_P (src_eqv_here))
4565e4b17023SJohn Marino src_const = src_eqv_here, src_const_elt = src_eqv_elt;
4566e4b17023SJohn Marino
4567e4b17023SJohn Marino /* If we don't know if the constant is in the table, get its
4568e4b17023SJohn Marino hash code and look it up. */
4569e4b17023SJohn Marino if (src_const && src_const_elt == 0)
4570e4b17023SJohn Marino {
4571e4b17023SJohn Marino sets[i].src_const_hash = HASH (src_const, mode);
4572e4b17023SJohn Marino src_const_elt = lookup (src_const, sets[i].src_const_hash, mode);
4573e4b17023SJohn Marino }
4574e4b17023SJohn Marino
4575e4b17023SJohn Marino sets[i].src_const = src_const;
4576e4b17023SJohn Marino sets[i].src_const_elt = src_const_elt;
4577e4b17023SJohn Marino
4578e4b17023SJohn Marino /* If the constant and our source are both in the table, mark them as
4579e4b17023SJohn Marino equivalent. Otherwise, if a constant is in the table but the source
4580e4b17023SJohn Marino isn't, set ELT to it. */
4581e4b17023SJohn Marino if (src_const_elt && elt
4582e4b17023SJohn Marino && src_const_elt->first_same_value != elt->first_same_value)
4583e4b17023SJohn Marino merge_equiv_classes (elt, src_const_elt);
4584e4b17023SJohn Marino else if (src_const_elt && elt == 0)
4585e4b17023SJohn Marino elt = src_const_elt;
4586e4b17023SJohn Marino
4587e4b17023SJohn Marino /* See if there is a register linearly related to a constant
4588e4b17023SJohn Marino equivalent of SRC. */
4589e4b17023SJohn Marino if (src_const
4590e4b17023SJohn Marino && (GET_CODE (src_const) == CONST
4591e4b17023SJohn Marino || (src_const_elt && src_const_elt->related_value != 0)))
4592e4b17023SJohn Marino {
4593e4b17023SJohn Marino src_related = use_related_value (src_const, src_const_elt);
4594e4b17023SJohn Marino if (src_related)
4595e4b17023SJohn Marino {
4596e4b17023SJohn Marino struct table_elt *src_related_elt
4597e4b17023SJohn Marino = lookup (src_related, HASH (src_related, mode), mode);
4598e4b17023SJohn Marino if (src_related_elt && elt)
4599e4b17023SJohn Marino {
4600e4b17023SJohn Marino if (elt->first_same_value
4601e4b17023SJohn Marino != src_related_elt->first_same_value)
4602e4b17023SJohn Marino /* This can occur when we previously saw a CONST
4603e4b17023SJohn Marino involving a SYMBOL_REF and then see the SYMBOL_REF
4604e4b17023SJohn Marino twice. Merge the involved classes. */
4605e4b17023SJohn Marino merge_equiv_classes (elt, src_related_elt);
4606e4b17023SJohn Marino
4607e4b17023SJohn Marino src_related = 0;
4608e4b17023SJohn Marino src_related_elt = 0;
4609e4b17023SJohn Marino }
4610e4b17023SJohn Marino else if (src_related_elt && elt == 0)
4611e4b17023SJohn Marino elt = src_related_elt;
4612e4b17023SJohn Marino }
4613e4b17023SJohn Marino }
4614e4b17023SJohn Marino
4615e4b17023SJohn Marino /* See if we have a CONST_INT that is already in a register in a
4616e4b17023SJohn Marino wider mode. */
4617e4b17023SJohn Marino
4618e4b17023SJohn Marino if (src_const && src_related == 0 && CONST_INT_P (src_const)
4619e4b17023SJohn Marino && GET_MODE_CLASS (mode) == MODE_INT
4620e4b17023SJohn Marino && GET_MODE_PRECISION (mode) < BITS_PER_WORD)
4621e4b17023SJohn Marino {
4622e4b17023SJohn Marino enum machine_mode wider_mode;
4623e4b17023SJohn Marino
4624e4b17023SJohn Marino for (wider_mode = GET_MODE_WIDER_MODE (mode);
4625e4b17023SJohn Marino wider_mode != VOIDmode
4626e4b17023SJohn Marino && GET_MODE_PRECISION (wider_mode) <= BITS_PER_WORD
4627e4b17023SJohn Marino && src_related == 0;
4628e4b17023SJohn Marino wider_mode = GET_MODE_WIDER_MODE (wider_mode))
4629e4b17023SJohn Marino {
4630e4b17023SJohn Marino struct table_elt *const_elt
4631e4b17023SJohn Marino = lookup (src_const, HASH (src_const, wider_mode), wider_mode);
4632e4b17023SJohn Marino
4633e4b17023SJohn Marino if (const_elt == 0)
4634e4b17023SJohn Marino continue;
4635e4b17023SJohn Marino
4636e4b17023SJohn Marino for (const_elt = const_elt->first_same_value;
4637e4b17023SJohn Marino const_elt; const_elt = const_elt->next_same_value)
4638e4b17023SJohn Marino if (REG_P (const_elt->exp))
4639e4b17023SJohn Marino {
4640e4b17023SJohn Marino src_related = gen_lowpart (mode, const_elt->exp);
4641e4b17023SJohn Marino break;
4642e4b17023SJohn Marino }
4643e4b17023SJohn Marino }
4644e4b17023SJohn Marino }
4645e4b17023SJohn Marino
4646e4b17023SJohn Marino /* Another possibility is that we have an AND with a constant in
4647e4b17023SJohn Marino a mode narrower than a word. If so, it might have been generated
4648e4b17023SJohn Marino as part of an "if" which would narrow the AND. If we already
4649e4b17023SJohn Marino have done the AND in a wider mode, we can use a SUBREG of that
4650e4b17023SJohn Marino value. */
4651e4b17023SJohn Marino
4652e4b17023SJohn Marino if (flag_expensive_optimizations && ! src_related
4653e4b17023SJohn Marino && GET_CODE (src) == AND && CONST_INT_P (XEXP (src, 1))
4654e4b17023SJohn Marino && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
4655e4b17023SJohn Marino {
4656e4b17023SJohn Marino enum machine_mode tmode;
4657e4b17023SJohn Marino rtx new_and = gen_rtx_AND (VOIDmode, NULL_RTX, XEXP (src, 1));
4658e4b17023SJohn Marino
4659e4b17023SJohn Marino for (tmode = GET_MODE_WIDER_MODE (mode);
4660e4b17023SJohn Marino GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
4661e4b17023SJohn Marino tmode = GET_MODE_WIDER_MODE (tmode))
4662e4b17023SJohn Marino {
4663e4b17023SJohn Marino rtx inner = gen_lowpart (tmode, XEXP (src, 0));
4664e4b17023SJohn Marino struct table_elt *larger_elt;
4665e4b17023SJohn Marino
4666e4b17023SJohn Marino if (inner)
4667e4b17023SJohn Marino {
4668e4b17023SJohn Marino PUT_MODE (new_and, tmode);
4669e4b17023SJohn Marino XEXP (new_and, 0) = inner;
4670e4b17023SJohn Marino larger_elt = lookup (new_and, HASH (new_and, tmode), tmode);
4671e4b17023SJohn Marino if (larger_elt == 0)
4672e4b17023SJohn Marino continue;
4673e4b17023SJohn Marino
4674e4b17023SJohn Marino for (larger_elt = larger_elt->first_same_value;
4675e4b17023SJohn Marino larger_elt; larger_elt = larger_elt->next_same_value)
4676e4b17023SJohn Marino if (REG_P (larger_elt->exp))
4677e4b17023SJohn Marino {
4678e4b17023SJohn Marino src_related
4679e4b17023SJohn Marino = gen_lowpart (mode, larger_elt->exp);
4680e4b17023SJohn Marino break;
4681e4b17023SJohn Marino }
4682e4b17023SJohn Marino
4683e4b17023SJohn Marino if (src_related)
4684e4b17023SJohn Marino break;
4685e4b17023SJohn Marino }
4686e4b17023SJohn Marino }
4687e4b17023SJohn Marino }
4688e4b17023SJohn Marino
4689e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
4690e4b17023SJohn Marino /* See if a MEM has already been loaded with a widening operation;
4691e4b17023SJohn Marino if it has, we can use a subreg of that. Many CISC machines
4692e4b17023SJohn Marino also have such operations, but this is only likely to be
4693e4b17023SJohn Marino beneficial on these machines. */
4694e4b17023SJohn Marino
4695e4b17023SJohn Marino if (flag_expensive_optimizations && src_related == 0
4696e4b17023SJohn Marino && (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
4697e4b17023SJohn Marino && GET_MODE_CLASS (mode) == MODE_INT
4698e4b17023SJohn Marino && MEM_P (src) && ! do_not_record
4699e4b17023SJohn Marino && LOAD_EXTEND_OP (mode) != UNKNOWN)
4700e4b17023SJohn Marino {
4701e4b17023SJohn Marino struct rtx_def memory_extend_buf;
4702e4b17023SJohn Marino rtx memory_extend_rtx = &memory_extend_buf;
4703e4b17023SJohn Marino enum machine_mode tmode;
4704e4b17023SJohn Marino
4705e4b17023SJohn Marino /* Set what we are trying to extend and the operation it might
4706e4b17023SJohn Marino have been extended with. */
4707e4b17023SJohn Marino memset (memory_extend_rtx, 0, sizeof(*memory_extend_rtx));
4708e4b17023SJohn Marino PUT_CODE (memory_extend_rtx, LOAD_EXTEND_OP (mode));
4709e4b17023SJohn Marino XEXP (memory_extend_rtx, 0) = src;
4710e4b17023SJohn Marino
4711e4b17023SJohn Marino for (tmode = GET_MODE_WIDER_MODE (mode);
4712e4b17023SJohn Marino GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
4713e4b17023SJohn Marino tmode = GET_MODE_WIDER_MODE (tmode))
4714e4b17023SJohn Marino {
4715e4b17023SJohn Marino struct table_elt *larger_elt;
4716e4b17023SJohn Marino
4717e4b17023SJohn Marino PUT_MODE (memory_extend_rtx, tmode);
4718e4b17023SJohn Marino larger_elt = lookup (memory_extend_rtx,
4719e4b17023SJohn Marino HASH (memory_extend_rtx, tmode), tmode);
4720e4b17023SJohn Marino if (larger_elt == 0)
4721e4b17023SJohn Marino continue;
4722e4b17023SJohn Marino
4723e4b17023SJohn Marino for (larger_elt = larger_elt->first_same_value;
4724e4b17023SJohn Marino larger_elt; larger_elt = larger_elt->next_same_value)
4725e4b17023SJohn Marino if (REG_P (larger_elt->exp))
4726e4b17023SJohn Marino {
4727e4b17023SJohn Marino src_related = gen_lowpart (mode, larger_elt->exp);
4728e4b17023SJohn Marino break;
4729e4b17023SJohn Marino }
4730e4b17023SJohn Marino
4731e4b17023SJohn Marino if (src_related)
4732e4b17023SJohn Marino break;
4733e4b17023SJohn Marino }
4734e4b17023SJohn Marino }
4735e4b17023SJohn Marino #endif /* LOAD_EXTEND_OP */
4736e4b17023SJohn Marino
4737e4b17023SJohn Marino /* Try to express the constant using a register+offset expression
4738e4b17023SJohn Marino derived from a constant anchor. */
4739e4b17023SJohn Marino
4740e4b17023SJohn Marino if (targetm.const_anchor
4741e4b17023SJohn Marino && !src_related
4742e4b17023SJohn Marino && src_const
4743e4b17023SJohn Marino && GET_CODE (src_const) == CONST_INT)
4744e4b17023SJohn Marino {
4745e4b17023SJohn Marino src_related = try_const_anchors (src_const, mode);
4746e4b17023SJohn Marino src_related_is_const_anchor = src_related != NULL_RTX;
4747e4b17023SJohn Marino }
4748e4b17023SJohn Marino
4749e4b17023SJohn Marino
4750e4b17023SJohn Marino if (src == src_folded)
4751e4b17023SJohn Marino src_folded = 0;
4752e4b17023SJohn Marino
4753e4b17023SJohn Marino /* At this point, ELT, if nonzero, points to a class of expressions
4754e4b17023SJohn Marino equivalent to the source of this SET and SRC, SRC_EQV, SRC_FOLDED,
4755e4b17023SJohn Marino and SRC_RELATED, if nonzero, each contain additional equivalent
4756e4b17023SJohn Marino expressions. Prune these latter expressions by deleting expressions
4757e4b17023SJohn Marino already in the equivalence class.
4758e4b17023SJohn Marino
4759e4b17023SJohn Marino Check for an equivalent identical to the destination. If found,
4760e4b17023SJohn Marino this is the preferred equivalent since it will likely lead to
4761e4b17023SJohn Marino elimination of the insn. Indicate this by placing it in
4762e4b17023SJohn Marino `src_related'. */
4763e4b17023SJohn Marino
4764e4b17023SJohn Marino if (elt)
4765e4b17023SJohn Marino elt = elt->first_same_value;
4766e4b17023SJohn Marino for (p = elt; p; p = p->next_same_value)
4767e4b17023SJohn Marino {
4768e4b17023SJohn Marino enum rtx_code code = GET_CODE (p->exp);
4769e4b17023SJohn Marino
4770e4b17023SJohn Marino /* If the expression is not valid, ignore it. Then we do not
4771e4b17023SJohn Marino have to check for validity below. In most cases, we can use
4772e4b17023SJohn Marino `rtx_equal_p', since canonicalization has already been done. */
4773e4b17023SJohn Marino if (code != REG && ! exp_equiv_p (p->exp, p->exp, 1, false))
4774e4b17023SJohn Marino continue;
4775e4b17023SJohn Marino
4776e4b17023SJohn Marino /* Also skip paradoxical subregs, unless that's what we're
4777e4b17023SJohn Marino looking for. */
4778e4b17023SJohn Marino if (paradoxical_subreg_p (p->exp)
4779e4b17023SJohn Marino && ! (src != 0
4780e4b17023SJohn Marino && GET_CODE (src) == SUBREG
4781e4b17023SJohn Marino && GET_MODE (src) == GET_MODE (p->exp)
4782e4b17023SJohn Marino && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
4783e4b17023SJohn Marino < GET_MODE_SIZE (GET_MODE (SUBREG_REG (p->exp))))))
4784e4b17023SJohn Marino continue;
4785e4b17023SJohn Marino
4786e4b17023SJohn Marino if (src && GET_CODE (src) == code && rtx_equal_p (src, p->exp))
4787e4b17023SJohn Marino src = 0;
4788e4b17023SJohn Marino else if (src_folded && GET_CODE (src_folded) == code
4789e4b17023SJohn Marino && rtx_equal_p (src_folded, p->exp))
4790e4b17023SJohn Marino src_folded = 0;
4791e4b17023SJohn Marino else if (src_eqv_here && GET_CODE (src_eqv_here) == code
4792e4b17023SJohn Marino && rtx_equal_p (src_eqv_here, p->exp))
4793e4b17023SJohn Marino src_eqv_here = 0;
4794e4b17023SJohn Marino else if (src_related && GET_CODE (src_related) == code
4795e4b17023SJohn Marino && rtx_equal_p (src_related, p->exp))
4796e4b17023SJohn Marino src_related = 0;
4797e4b17023SJohn Marino
4798e4b17023SJohn Marino /* This is the same as the destination of the insns, we want
4799e4b17023SJohn Marino to prefer it. Copy it to src_related. The code below will
4800e4b17023SJohn Marino then give it a negative cost. */
4801e4b17023SJohn Marino if (GET_CODE (dest) == code && rtx_equal_p (p->exp, dest))
4802e4b17023SJohn Marino src_related = dest;
4803e4b17023SJohn Marino }
4804e4b17023SJohn Marino
4805e4b17023SJohn Marino /* Find the cheapest valid equivalent, trying all the available
4806e4b17023SJohn Marino possibilities. Prefer items not in the hash table to ones
4807e4b17023SJohn Marino that are when they are equal cost. Note that we can never
4808e4b17023SJohn Marino worsen an insn as the current contents will also succeed.
4809e4b17023SJohn Marino If we find an equivalent identical to the destination, use it as best,
4810e4b17023SJohn Marino since this insn will probably be eliminated in that case. */
4811e4b17023SJohn Marino if (src)
4812e4b17023SJohn Marino {
4813e4b17023SJohn Marino if (rtx_equal_p (src, dest))
4814e4b17023SJohn Marino src_cost = src_regcost = -1;
4815e4b17023SJohn Marino else
4816e4b17023SJohn Marino {
4817e4b17023SJohn Marino src_cost = COST (src);
4818e4b17023SJohn Marino src_regcost = approx_reg_cost (src);
4819e4b17023SJohn Marino }
4820e4b17023SJohn Marino }
4821e4b17023SJohn Marino
4822e4b17023SJohn Marino if (src_eqv_here)
4823e4b17023SJohn Marino {
4824e4b17023SJohn Marino if (rtx_equal_p (src_eqv_here, dest))
4825e4b17023SJohn Marino src_eqv_cost = src_eqv_regcost = -1;
4826e4b17023SJohn Marino else
4827e4b17023SJohn Marino {
4828e4b17023SJohn Marino src_eqv_cost = COST (src_eqv_here);
4829e4b17023SJohn Marino src_eqv_regcost = approx_reg_cost (src_eqv_here);
4830e4b17023SJohn Marino }
4831e4b17023SJohn Marino }
4832e4b17023SJohn Marino
4833e4b17023SJohn Marino if (src_folded)
4834e4b17023SJohn Marino {
4835e4b17023SJohn Marino if (rtx_equal_p (src_folded, dest))
4836e4b17023SJohn Marino src_folded_cost = src_folded_regcost = -1;
4837e4b17023SJohn Marino else
4838e4b17023SJohn Marino {
4839e4b17023SJohn Marino src_folded_cost = COST (src_folded);
4840e4b17023SJohn Marino src_folded_regcost = approx_reg_cost (src_folded);
4841e4b17023SJohn Marino }
4842e4b17023SJohn Marino }
4843e4b17023SJohn Marino
4844e4b17023SJohn Marino if (src_related)
4845e4b17023SJohn Marino {
4846e4b17023SJohn Marino if (rtx_equal_p (src_related, dest))
4847e4b17023SJohn Marino src_related_cost = src_related_regcost = -1;
4848e4b17023SJohn Marino else
4849e4b17023SJohn Marino {
4850e4b17023SJohn Marino src_related_cost = COST (src_related);
4851e4b17023SJohn Marino src_related_regcost = approx_reg_cost (src_related);
4852e4b17023SJohn Marino
4853e4b17023SJohn Marino /* If a const-anchor is used to synthesize a constant that
4854e4b17023SJohn Marino normally requires multiple instructions then slightly prefer
4855e4b17023SJohn Marino it over the original sequence. These instructions are likely
4856e4b17023SJohn Marino to become redundant now. We can't compare against the cost
4857e4b17023SJohn Marino of src_eqv_here because, on MIPS for example, multi-insn
4858e4b17023SJohn Marino constants have zero cost; they are assumed to be hoisted from
4859e4b17023SJohn Marino loops. */
4860e4b17023SJohn Marino if (src_related_is_const_anchor
4861e4b17023SJohn Marino && src_related_cost == src_cost
4862e4b17023SJohn Marino && src_eqv_here)
4863e4b17023SJohn Marino src_related_cost--;
4864e4b17023SJohn Marino }
4865e4b17023SJohn Marino }
4866e4b17023SJohn Marino
4867e4b17023SJohn Marino /* If this was an indirect jump insn, a known label will really be
4868e4b17023SJohn Marino cheaper even though it looks more expensive. */
4869e4b17023SJohn Marino if (dest == pc_rtx && src_const && GET_CODE (src_const) == LABEL_REF)
4870e4b17023SJohn Marino src_folded = src_const, src_folded_cost = src_folded_regcost = -1;
4871e4b17023SJohn Marino
4872e4b17023SJohn Marino /* Terminate loop when replacement made. This must terminate since
4873e4b17023SJohn Marino the current contents will be tested and will always be valid. */
4874e4b17023SJohn Marino while (1)
4875e4b17023SJohn Marino {
4876e4b17023SJohn Marino rtx trial;
4877e4b17023SJohn Marino
4878e4b17023SJohn Marino /* Skip invalid entries. */
4879e4b17023SJohn Marino while (elt && !REG_P (elt->exp)
4880e4b17023SJohn Marino && ! exp_equiv_p (elt->exp, elt->exp, 1, false))
4881e4b17023SJohn Marino elt = elt->next_same_value;
4882e4b17023SJohn Marino
4883e4b17023SJohn Marino /* A paradoxical subreg would be bad here: it'll be the right
4884e4b17023SJohn Marino size, but later may be adjusted so that the upper bits aren't
4885e4b17023SJohn Marino what we want. So reject it. */
4886e4b17023SJohn Marino if (elt != 0
4887e4b17023SJohn Marino && paradoxical_subreg_p (elt->exp)
4888e4b17023SJohn Marino /* It is okay, though, if the rtx we're trying to match
4889e4b17023SJohn Marino will ignore any of the bits we can't predict. */
4890e4b17023SJohn Marino && ! (src != 0
4891e4b17023SJohn Marino && GET_CODE (src) == SUBREG
4892e4b17023SJohn Marino && GET_MODE (src) == GET_MODE (elt->exp)
4893e4b17023SJohn Marino && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
4894e4b17023SJohn Marino < GET_MODE_SIZE (GET_MODE (SUBREG_REG (elt->exp))))))
4895e4b17023SJohn Marino {
4896e4b17023SJohn Marino elt = elt->next_same_value;
4897e4b17023SJohn Marino continue;
4898e4b17023SJohn Marino }
4899e4b17023SJohn Marino
4900e4b17023SJohn Marino if (elt)
4901e4b17023SJohn Marino {
4902e4b17023SJohn Marino src_elt_cost = elt->cost;
4903e4b17023SJohn Marino src_elt_regcost = elt->regcost;
4904e4b17023SJohn Marino }
4905e4b17023SJohn Marino
4906e4b17023SJohn Marino /* Find cheapest and skip it for the next time. For items
4907e4b17023SJohn Marino of equal cost, use this order:
4908e4b17023SJohn Marino src_folded, src, src_eqv, src_related and hash table entry. */
4909e4b17023SJohn Marino if (src_folded
4910e4b17023SJohn Marino && preferable (src_folded_cost, src_folded_regcost,
4911e4b17023SJohn Marino src_cost, src_regcost) <= 0
4912e4b17023SJohn Marino && preferable (src_folded_cost, src_folded_regcost,
4913e4b17023SJohn Marino src_eqv_cost, src_eqv_regcost) <= 0
4914e4b17023SJohn Marino && preferable (src_folded_cost, src_folded_regcost,
4915e4b17023SJohn Marino src_related_cost, src_related_regcost) <= 0
4916e4b17023SJohn Marino && preferable (src_folded_cost, src_folded_regcost,
4917e4b17023SJohn Marino src_elt_cost, src_elt_regcost) <= 0)
4918e4b17023SJohn Marino {
4919e4b17023SJohn Marino trial = src_folded, src_folded_cost = MAX_COST;
4920e4b17023SJohn Marino if (src_folded_force_flag)
4921e4b17023SJohn Marino {
4922e4b17023SJohn Marino rtx forced = force_const_mem (mode, trial);
4923e4b17023SJohn Marino if (forced)
4924e4b17023SJohn Marino trial = forced;
4925e4b17023SJohn Marino }
4926e4b17023SJohn Marino }
4927e4b17023SJohn Marino else if (src
4928e4b17023SJohn Marino && preferable (src_cost, src_regcost,
4929e4b17023SJohn Marino src_eqv_cost, src_eqv_regcost) <= 0
4930e4b17023SJohn Marino && preferable (src_cost, src_regcost,
4931e4b17023SJohn Marino src_related_cost, src_related_regcost) <= 0
4932e4b17023SJohn Marino && preferable (src_cost, src_regcost,
4933e4b17023SJohn Marino src_elt_cost, src_elt_regcost) <= 0)
4934e4b17023SJohn Marino trial = src, src_cost = MAX_COST;
4935e4b17023SJohn Marino else if (src_eqv_here
4936e4b17023SJohn Marino && preferable (src_eqv_cost, src_eqv_regcost,
4937e4b17023SJohn Marino src_related_cost, src_related_regcost) <= 0
4938e4b17023SJohn Marino && preferable (src_eqv_cost, src_eqv_regcost,
4939e4b17023SJohn Marino src_elt_cost, src_elt_regcost) <= 0)
4940e4b17023SJohn Marino trial = src_eqv_here, src_eqv_cost = MAX_COST;
4941e4b17023SJohn Marino else if (src_related
4942e4b17023SJohn Marino && preferable (src_related_cost, src_related_regcost,
4943e4b17023SJohn Marino src_elt_cost, src_elt_regcost) <= 0)
4944e4b17023SJohn Marino trial = src_related, src_related_cost = MAX_COST;
4945e4b17023SJohn Marino else
4946e4b17023SJohn Marino {
4947e4b17023SJohn Marino trial = elt->exp;
4948e4b17023SJohn Marino elt = elt->next_same_value;
4949e4b17023SJohn Marino src_elt_cost = MAX_COST;
4950e4b17023SJohn Marino }
4951e4b17023SJohn Marino
4952e4b17023SJohn Marino /* Avoid creation of overlapping memory moves. */
4953e4b17023SJohn Marino if (MEM_P (trial) && MEM_P (SET_DEST (sets[i].rtl)))
4954e4b17023SJohn Marino {
4955e4b17023SJohn Marino rtx src, dest;
4956e4b17023SJohn Marino
4957e4b17023SJohn Marino /* BLKmode moves are not handled by cse anyway. */
4958e4b17023SJohn Marino if (GET_MODE (trial) == BLKmode)
4959e4b17023SJohn Marino break;
4960e4b17023SJohn Marino
4961e4b17023SJohn Marino src = canon_rtx (trial);
4962e4b17023SJohn Marino dest = canon_rtx (SET_DEST (sets[i].rtl));
4963e4b17023SJohn Marino
4964e4b17023SJohn Marino if (!MEM_P (src) || !MEM_P (dest)
4965e4b17023SJohn Marino || !nonoverlapping_memrefs_p (src, dest, false))
4966e4b17023SJohn Marino break;
4967e4b17023SJohn Marino }
4968e4b17023SJohn Marino
4969e4b17023SJohn Marino /* Try to optimize
4970e4b17023SJohn Marino (set (reg:M N) (const_int A))
4971e4b17023SJohn Marino (set (reg:M2 O) (const_int B))
4972e4b17023SJohn Marino (set (zero_extract:M2 (reg:M N) (const_int C) (const_int D))
4973e4b17023SJohn Marino (reg:M2 O)). */
4974e4b17023SJohn Marino if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT
4975e4b17023SJohn Marino && CONST_INT_P (trial)
4976e4b17023SJohn Marino && CONST_INT_P (XEXP (SET_DEST (sets[i].rtl), 1))
4977e4b17023SJohn Marino && CONST_INT_P (XEXP (SET_DEST (sets[i].rtl), 2))
4978e4b17023SJohn Marino && REG_P (XEXP (SET_DEST (sets[i].rtl), 0))
4979e4b17023SJohn Marino && (GET_MODE_PRECISION (GET_MODE (SET_DEST (sets[i].rtl)))
4980e4b17023SJohn Marino >= INTVAL (XEXP (SET_DEST (sets[i].rtl), 1)))
4981e4b17023SJohn Marino && ((unsigned) INTVAL (XEXP (SET_DEST (sets[i].rtl), 1))
4982e4b17023SJohn Marino + (unsigned) INTVAL (XEXP (SET_DEST (sets[i].rtl), 2))
4983e4b17023SJohn Marino <= HOST_BITS_PER_WIDE_INT))
4984e4b17023SJohn Marino {
4985e4b17023SJohn Marino rtx dest_reg = XEXP (SET_DEST (sets[i].rtl), 0);
4986e4b17023SJohn Marino rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
4987e4b17023SJohn Marino rtx pos = XEXP (SET_DEST (sets[i].rtl), 2);
4988e4b17023SJohn Marino unsigned int dest_hash = HASH (dest_reg, GET_MODE (dest_reg));
4989e4b17023SJohn Marino struct table_elt *dest_elt
4990e4b17023SJohn Marino = lookup (dest_reg, dest_hash, GET_MODE (dest_reg));
4991e4b17023SJohn Marino rtx dest_cst = NULL;
4992e4b17023SJohn Marino
4993e4b17023SJohn Marino if (dest_elt)
4994e4b17023SJohn Marino for (p = dest_elt->first_same_value; p; p = p->next_same_value)
4995e4b17023SJohn Marino if (p->is_const && CONST_INT_P (p->exp))
4996e4b17023SJohn Marino {
4997e4b17023SJohn Marino dest_cst = p->exp;
4998e4b17023SJohn Marino break;
4999e4b17023SJohn Marino }
5000e4b17023SJohn Marino if (dest_cst)
5001e4b17023SJohn Marino {
5002e4b17023SJohn Marino HOST_WIDE_INT val = INTVAL (dest_cst);
5003e4b17023SJohn Marino HOST_WIDE_INT mask;
5004e4b17023SJohn Marino unsigned int shift;
5005e4b17023SJohn Marino if (BITS_BIG_ENDIAN)
5006e4b17023SJohn Marino shift = GET_MODE_PRECISION (GET_MODE (dest_reg))
5007e4b17023SJohn Marino - INTVAL (pos) - INTVAL (width);
5008e4b17023SJohn Marino else
5009e4b17023SJohn Marino shift = INTVAL (pos);
5010e4b17023SJohn Marino if (INTVAL (width) == HOST_BITS_PER_WIDE_INT)
5011e4b17023SJohn Marino mask = ~(HOST_WIDE_INT) 0;
5012e4b17023SJohn Marino else
5013e4b17023SJohn Marino mask = ((HOST_WIDE_INT) 1 << INTVAL (width)) - 1;
5014e4b17023SJohn Marino val &= ~(mask << shift);
5015e4b17023SJohn Marino val |= (INTVAL (trial) & mask) << shift;
5016e4b17023SJohn Marino val = trunc_int_for_mode (val, GET_MODE (dest_reg));
5017e4b17023SJohn Marino validate_unshare_change (insn, &SET_DEST (sets[i].rtl),
5018e4b17023SJohn Marino dest_reg, 1);
5019e4b17023SJohn Marino validate_unshare_change (insn, &SET_SRC (sets[i].rtl),
5020e4b17023SJohn Marino GEN_INT (val), 1);
5021e4b17023SJohn Marino if (apply_change_group ())
5022e4b17023SJohn Marino {
5023e4b17023SJohn Marino rtx note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
5024e4b17023SJohn Marino if (note)
5025e4b17023SJohn Marino {
5026e4b17023SJohn Marino remove_note (insn, note);
5027e4b17023SJohn Marino df_notes_rescan (insn);
5028e4b17023SJohn Marino }
5029e4b17023SJohn Marino src_eqv = NULL_RTX;
5030e4b17023SJohn Marino src_eqv_elt = NULL;
5031e4b17023SJohn Marino src_eqv_volatile = 0;
5032e4b17023SJohn Marino src_eqv_in_memory = 0;
5033e4b17023SJohn Marino src_eqv_hash = 0;
5034e4b17023SJohn Marino repeat = true;
5035e4b17023SJohn Marino break;
5036e4b17023SJohn Marino }
5037e4b17023SJohn Marino }
5038e4b17023SJohn Marino }
5039e4b17023SJohn Marino
5040e4b17023SJohn Marino /* We don't normally have an insn matching (set (pc) (pc)), so
5041e4b17023SJohn Marino check for this separately here. We will delete such an
5042e4b17023SJohn Marino insn below.
5043e4b17023SJohn Marino
5044e4b17023SJohn Marino For other cases such as a table jump or conditional jump
5045e4b17023SJohn Marino where we know the ultimate target, go ahead and replace the
5046e4b17023SJohn Marino operand. While that may not make a valid insn, we will
5047e4b17023SJohn Marino reemit the jump below (and also insert any necessary
5048e4b17023SJohn Marino barriers). */
5049e4b17023SJohn Marino if (n_sets == 1 && dest == pc_rtx
5050e4b17023SJohn Marino && (trial == pc_rtx
5051e4b17023SJohn Marino || (GET_CODE (trial) == LABEL_REF
5052e4b17023SJohn Marino && ! condjump_p (insn))))
5053e4b17023SJohn Marino {
5054e4b17023SJohn Marino /* Don't substitute non-local labels, this confuses CFG. */
5055e4b17023SJohn Marino if (GET_CODE (trial) == LABEL_REF
5056e4b17023SJohn Marino && LABEL_REF_NONLOCAL_P (trial))
5057e4b17023SJohn Marino continue;
5058e4b17023SJohn Marino
5059e4b17023SJohn Marino SET_SRC (sets[i].rtl) = trial;
5060e4b17023SJohn Marino cse_jumps_altered = true;
5061e4b17023SJohn Marino break;
5062e4b17023SJohn Marino }
5063e4b17023SJohn Marino
5064e4b17023SJohn Marino /* Reject certain invalid forms of CONST that we create. */
5065e4b17023SJohn Marino else if (CONSTANT_P (trial)
5066e4b17023SJohn Marino && GET_CODE (trial) == CONST
5067e4b17023SJohn Marino /* Reject cases that will cause decode_rtx_const to
5068e4b17023SJohn Marino die. On the alpha when simplifying a switch, we
5069e4b17023SJohn Marino get (const (truncate (minus (label_ref)
5070e4b17023SJohn Marino (label_ref)))). */
5071e4b17023SJohn Marino && (GET_CODE (XEXP (trial, 0)) == TRUNCATE
5072e4b17023SJohn Marino /* Likewise on IA-64, except without the
5073e4b17023SJohn Marino truncate. */
5074e4b17023SJohn Marino || (GET_CODE (XEXP (trial, 0)) == MINUS
5075e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (trial, 0), 0)) == LABEL_REF
5076e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (trial, 0), 1)) == LABEL_REF)))
5077e4b17023SJohn Marino /* Do nothing for this case. */
5078e4b17023SJohn Marino ;
5079e4b17023SJohn Marino
5080e4b17023SJohn Marino /* Look for a substitution that makes a valid insn. */
5081e4b17023SJohn Marino else if (validate_unshare_change
5082e4b17023SJohn Marino (insn, &SET_SRC (sets[i].rtl), trial, 0))
5083e4b17023SJohn Marino {
5084e4b17023SJohn Marino rtx new_rtx = canon_reg (SET_SRC (sets[i].rtl), insn);
5085e4b17023SJohn Marino
5086e4b17023SJohn Marino /* The result of apply_change_group can be ignored; see
5087e4b17023SJohn Marino canon_reg. */
5088e4b17023SJohn Marino
5089e4b17023SJohn Marino validate_change (insn, &SET_SRC (sets[i].rtl), new_rtx, 1);
5090e4b17023SJohn Marino apply_change_group ();
5091e4b17023SJohn Marino
5092e4b17023SJohn Marino break;
5093e4b17023SJohn Marino }
5094e4b17023SJohn Marino
5095e4b17023SJohn Marino /* If we previously found constant pool entries for
5096e4b17023SJohn Marino constants and this is a constant, try making a
5097e4b17023SJohn Marino pool entry. Put it in src_folded unless we already have done
5098e4b17023SJohn Marino this since that is where it likely came from. */
5099e4b17023SJohn Marino
5100e4b17023SJohn Marino else if (constant_pool_entries_cost
5101e4b17023SJohn Marino && CONSTANT_P (trial)
5102e4b17023SJohn Marino && (src_folded == 0
5103e4b17023SJohn Marino || (!MEM_P (src_folded)
5104e4b17023SJohn Marino && ! src_folded_force_flag))
5105e4b17023SJohn Marino && GET_MODE_CLASS (mode) != MODE_CC
5106e4b17023SJohn Marino && mode != VOIDmode)
5107e4b17023SJohn Marino {
5108e4b17023SJohn Marino src_folded_force_flag = 1;
5109e4b17023SJohn Marino src_folded = trial;
5110e4b17023SJohn Marino src_folded_cost = constant_pool_entries_cost;
5111e4b17023SJohn Marino src_folded_regcost = constant_pool_entries_regcost;
5112e4b17023SJohn Marino }
5113e4b17023SJohn Marino }
5114e4b17023SJohn Marino
5115e4b17023SJohn Marino /* If we changed the insn too much, handle this set from scratch. */
5116e4b17023SJohn Marino if (repeat)
5117e4b17023SJohn Marino {
5118e4b17023SJohn Marino i--;
5119e4b17023SJohn Marino continue;
5120e4b17023SJohn Marino }
5121e4b17023SJohn Marino
5122e4b17023SJohn Marino src = SET_SRC (sets[i].rtl);
5123e4b17023SJohn Marino
5124e4b17023SJohn Marino /* In general, it is good to have a SET with SET_SRC == SET_DEST.
5125e4b17023SJohn Marino However, there is an important exception: If both are registers
5126e4b17023SJohn Marino that are not the head of their equivalence class, replace SET_SRC
5127e4b17023SJohn Marino with the head of the class. If we do not do this, we will have
5128e4b17023SJohn Marino both registers live over a portion of the basic block. This way,
5129e4b17023SJohn Marino their lifetimes will likely abut instead of overlapping. */
5130e4b17023SJohn Marino if (REG_P (dest)
5131e4b17023SJohn Marino && REGNO_QTY_VALID_P (REGNO (dest)))
5132e4b17023SJohn Marino {
5133e4b17023SJohn Marino int dest_q = REG_QTY (REGNO (dest));
5134e4b17023SJohn Marino struct qty_table_elem *dest_ent = &qty_table[dest_q];
5135e4b17023SJohn Marino
5136e4b17023SJohn Marino if (dest_ent->mode == GET_MODE (dest)
5137e4b17023SJohn Marino && dest_ent->first_reg != REGNO (dest)
5138e4b17023SJohn Marino && REG_P (src) && REGNO (src) == REGNO (dest)
5139e4b17023SJohn Marino /* Don't do this if the original insn had a hard reg as
5140e4b17023SJohn Marino SET_SRC or SET_DEST. */
5141e4b17023SJohn Marino && (!REG_P (sets[i].src)
5142e4b17023SJohn Marino || REGNO (sets[i].src) >= FIRST_PSEUDO_REGISTER)
5143e4b17023SJohn Marino && (!REG_P (dest) || REGNO (dest) >= FIRST_PSEUDO_REGISTER))
5144e4b17023SJohn Marino /* We can't call canon_reg here because it won't do anything if
5145e4b17023SJohn Marino SRC is a hard register. */
5146e4b17023SJohn Marino {
5147e4b17023SJohn Marino int src_q = REG_QTY (REGNO (src));
5148e4b17023SJohn Marino struct qty_table_elem *src_ent = &qty_table[src_q];
5149e4b17023SJohn Marino int first = src_ent->first_reg;
5150e4b17023SJohn Marino rtx new_src
5151e4b17023SJohn Marino = (first >= FIRST_PSEUDO_REGISTER
5152e4b17023SJohn Marino ? regno_reg_rtx[first] : gen_rtx_REG (GET_MODE (src), first));
5153e4b17023SJohn Marino
5154e4b17023SJohn Marino /* We must use validate-change even for this, because this
5155e4b17023SJohn Marino might be a special no-op instruction, suitable only to
5156e4b17023SJohn Marino tag notes onto. */
5157e4b17023SJohn Marino if (validate_change (insn, &SET_SRC (sets[i].rtl), new_src, 0))
5158e4b17023SJohn Marino {
5159e4b17023SJohn Marino src = new_src;
5160e4b17023SJohn Marino /* If we had a constant that is cheaper than what we are now
5161e4b17023SJohn Marino setting SRC to, use that constant. We ignored it when we
5162e4b17023SJohn Marino thought we could make this into a no-op. */
5163e4b17023SJohn Marino if (src_const && COST (src_const) < COST (src)
5164e4b17023SJohn Marino && validate_change (insn, &SET_SRC (sets[i].rtl),
5165e4b17023SJohn Marino src_const, 0))
5166e4b17023SJohn Marino src = src_const;
5167e4b17023SJohn Marino }
5168e4b17023SJohn Marino }
5169e4b17023SJohn Marino }
5170e4b17023SJohn Marino
5171e4b17023SJohn Marino /* If we made a change, recompute SRC values. */
5172e4b17023SJohn Marino if (src != sets[i].src)
5173e4b17023SJohn Marino {
5174e4b17023SJohn Marino do_not_record = 0;
5175e4b17023SJohn Marino hash_arg_in_memory = 0;
5176e4b17023SJohn Marino sets[i].src = src;
5177e4b17023SJohn Marino sets[i].src_hash = HASH (src, mode);
5178e4b17023SJohn Marino sets[i].src_volatile = do_not_record;
5179e4b17023SJohn Marino sets[i].src_in_memory = hash_arg_in_memory;
5180e4b17023SJohn Marino sets[i].src_elt = lookup (src, sets[i].src_hash, mode);
5181e4b17023SJohn Marino }
5182e4b17023SJohn Marino
5183e4b17023SJohn Marino /* If this is a single SET, we are setting a register, and we have an
5184e4b17023SJohn Marino equivalent constant, we want to add a REG_NOTE. We don't want
5185e4b17023SJohn Marino to write a REG_EQUAL note for a constant pseudo since verifying that
5186e4b17023SJohn Marino that pseudo hasn't been eliminated is a pain. Such a note also
5187e4b17023SJohn Marino won't help anything.
5188e4b17023SJohn Marino
5189e4b17023SJohn Marino Avoid a REG_EQUAL note for (CONST (MINUS (LABEL_REF) (LABEL_REF)))
5190e4b17023SJohn Marino which can be created for a reference to a compile time computable
5191e4b17023SJohn Marino entry in a jump table. */
5192e4b17023SJohn Marino
5193e4b17023SJohn Marino if (n_sets == 1 && src_const && REG_P (dest)
5194e4b17023SJohn Marino && !REG_P (src_const)
5195e4b17023SJohn Marino && ! (GET_CODE (src_const) == CONST
5196e4b17023SJohn Marino && GET_CODE (XEXP (src_const, 0)) == MINUS
5197e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (src_const, 0), 0)) == LABEL_REF
5198e4b17023SJohn Marino && GET_CODE (XEXP (XEXP (src_const, 0), 1)) == LABEL_REF))
5199e4b17023SJohn Marino {
5200e4b17023SJohn Marino /* We only want a REG_EQUAL note if src_const != src. */
5201e4b17023SJohn Marino if (! rtx_equal_p (src, src_const))
5202e4b17023SJohn Marino {
5203e4b17023SJohn Marino /* Make sure that the rtx is not shared. */
5204e4b17023SJohn Marino src_const = copy_rtx (src_const);
5205e4b17023SJohn Marino
5206e4b17023SJohn Marino /* Record the actual constant value in a REG_EQUAL note,
5207e4b17023SJohn Marino making a new one if one does not already exist. */
5208e4b17023SJohn Marino set_unique_reg_note (insn, REG_EQUAL, src_const);
5209e4b17023SJohn Marino df_notes_rescan (insn);
5210e4b17023SJohn Marino }
5211e4b17023SJohn Marino }
5212e4b17023SJohn Marino
5213e4b17023SJohn Marino /* Now deal with the destination. */
5214e4b17023SJohn Marino do_not_record = 0;
5215e4b17023SJohn Marino
5216e4b17023SJohn Marino /* Look within any ZERO_EXTRACT to the MEM or REG within it. */
5217e4b17023SJohn Marino while (GET_CODE (dest) == SUBREG
5218e4b17023SJohn Marino || GET_CODE (dest) == ZERO_EXTRACT
5219e4b17023SJohn Marino || GET_CODE (dest) == STRICT_LOW_PART)
5220e4b17023SJohn Marino dest = XEXP (dest, 0);
5221e4b17023SJohn Marino
5222e4b17023SJohn Marino sets[i].inner_dest = dest;
5223e4b17023SJohn Marino
5224e4b17023SJohn Marino if (MEM_P (dest))
5225e4b17023SJohn Marino {
5226e4b17023SJohn Marino #ifdef PUSH_ROUNDING
5227e4b17023SJohn Marino /* Stack pushes invalidate the stack pointer. */
5228e4b17023SJohn Marino rtx addr = XEXP (dest, 0);
5229e4b17023SJohn Marino if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC
5230e4b17023SJohn Marino && XEXP (addr, 0) == stack_pointer_rtx)
5231e4b17023SJohn Marino invalidate (stack_pointer_rtx, VOIDmode);
5232e4b17023SJohn Marino #endif
5233e4b17023SJohn Marino dest = fold_rtx (dest, insn);
5234e4b17023SJohn Marino }
5235e4b17023SJohn Marino
5236e4b17023SJohn Marino /* Compute the hash code of the destination now,
5237e4b17023SJohn Marino before the effects of this instruction are recorded,
5238e4b17023SJohn Marino since the register values used in the address computation
5239e4b17023SJohn Marino are those before this instruction. */
5240e4b17023SJohn Marino sets[i].dest_hash = HASH (dest, mode);
5241e4b17023SJohn Marino
5242e4b17023SJohn Marino /* Don't enter a bit-field in the hash table
5243e4b17023SJohn Marino because the value in it after the store
5244e4b17023SJohn Marino may not equal what was stored, due to truncation. */
5245e4b17023SJohn Marino
5246e4b17023SJohn Marino if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT)
5247e4b17023SJohn Marino {
5248e4b17023SJohn Marino rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
5249e4b17023SJohn Marino
5250e4b17023SJohn Marino if (src_const != 0 && CONST_INT_P (src_const)
5251e4b17023SJohn Marino && CONST_INT_P (width)
5252e4b17023SJohn Marino && INTVAL (width) < HOST_BITS_PER_WIDE_INT
5253e4b17023SJohn Marino && ! (INTVAL (src_const)
5254e4b17023SJohn Marino & ((HOST_WIDE_INT) (-1) << INTVAL (width))))
5255e4b17023SJohn Marino /* Exception: if the value is constant,
5256e4b17023SJohn Marino and it won't be truncated, record it. */
5257e4b17023SJohn Marino ;
5258e4b17023SJohn Marino else
5259e4b17023SJohn Marino {
5260e4b17023SJohn Marino /* This is chosen so that the destination will be invalidated
5261e4b17023SJohn Marino but no new value will be recorded.
5262e4b17023SJohn Marino We must invalidate because sometimes constant
5263e4b17023SJohn Marino values can be recorded for bitfields. */
5264e4b17023SJohn Marino sets[i].src_elt = 0;
5265e4b17023SJohn Marino sets[i].src_volatile = 1;
5266e4b17023SJohn Marino src_eqv = 0;
5267e4b17023SJohn Marino src_eqv_elt = 0;
5268e4b17023SJohn Marino }
5269e4b17023SJohn Marino }
5270e4b17023SJohn Marino
5271e4b17023SJohn Marino /* If only one set in a JUMP_INSN and it is now a no-op, we can delete
5272e4b17023SJohn Marino the insn. */
5273e4b17023SJohn Marino else if (n_sets == 1 && dest == pc_rtx && src == pc_rtx)
5274e4b17023SJohn Marino {
5275e4b17023SJohn Marino /* One less use of the label this insn used to jump to. */
5276e4b17023SJohn Marino delete_insn_and_edges (insn);
5277e4b17023SJohn Marino cse_jumps_altered = true;
5278e4b17023SJohn Marino /* No more processing for this set. */
5279e4b17023SJohn Marino sets[i].rtl = 0;
5280e4b17023SJohn Marino }
5281e4b17023SJohn Marino
5282e4b17023SJohn Marino /* If this SET is now setting PC to a label, we know it used to
5283e4b17023SJohn Marino be a conditional or computed branch. */
5284e4b17023SJohn Marino else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF
5285e4b17023SJohn Marino && !LABEL_REF_NONLOCAL_P (src))
5286e4b17023SJohn Marino {
5287e4b17023SJohn Marino /* We reemit the jump in as many cases as possible just in
5288e4b17023SJohn Marino case the form of an unconditional jump is significantly
5289e4b17023SJohn Marino different than a computed jump or conditional jump.
5290e4b17023SJohn Marino
5291e4b17023SJohn Marino If this insn has multiple sets, then reemitting the
5292e4b17023SJohn Marino jump is nontrivial. So instead we just force rerecognition
5293e4b17023SJohn Marino and hope for the best. */
5294e4b17023SJohn Marino if (n_sets == 1)
5295e4b17023SJohn Marino {
5296e4b17023SJohn Marino rtx new_rtx, note;
5297e4b17023SJohn Marino
5298e4b17023SJohn Marino new_rtx = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn);
5299e4b17023SJohn Marino JUMP_LABEL (new_rtx) = XEXP (src, 0);
5300e4b17023SJohn Marino LABEL_NUSES (XEXP (src, 0))++;
5301e4b17023SJohn Marino
5302e4b17023SJohn Marino /* Make sure to copy over REG_NON_LOCAL_GOTO. */
5303e4b17023SJohn Marino note = find_reg_note (insn, REG_NON_LOCAL_GOTO, 0);
5304e4b17023SJohn Marino if (note)
5305e4b17023SJohn Marino {
5306e4b17023SJohn Marino XEXP (note, 1) = NULL_RTX;
5307e4b17023SJohn Marino REG_NOTES (new_rtx) = note;
5308e4b17023SJohn Marino }
5309e4b17023SJohn Marino
5310e4b17023SJohn Marino delete_insn_and_edges (insn);
5311e4b17023SJohn Marino insn = new_rtx;
5312e4b17023SJohn Marino }
5313e4b17023SJohn Marino else
5314e4b17023SJohn Marino INSN_CODE (insn) = -1;
5315e4b17023SJohn Marino
5316e4b17023SJohn Marino /* Do not bother deleting any unreachable code, let jump do it. */
5317e4b17023SJohn Marino cse_jumps_altered = true;
5318e4b17023SJohn Marino sets[i].rtl = 0;
5319e4b17023SJohn Marino }
5320e4b17023SJohn Marino
5321e4b17023SJohn Marino /* If destination is volatile, invalidate it and then do no further
5322e4b17023SJohn Marino processing for this assignment. */
5323e4b17023SJohn Marino
5324e4b17023SJohn Marino else if (do_not_record)
5325e4b17023SJohn Marino {
5326e4b17023SJohn Marino if (REG_P (dest) || GET_CODE (dest) == SUBREG)
5327e4b17023SJohn Marino invalidate (dest, VOIDmode);
5328e4b17023SJohn Marino else if (MEM_P (dest))
5329e4b17023SJohn Marino invalidate (dest, VOIDmode);
5330e4b17023SJohn Marino else if (GET_CODE (dest) == STRICT_LOW_PART
5331e4b17023SJohn Marino || GET_CODE (dest) == ZERO_EXTRACT)
5332e4b17023SJohn Marino invalidate (XEXP (dest, 0), GET_MODE (dest));
5333e4b17023SJohn Marino sets[i].rtl = 0;
5334e4b17023SJohn Marino }
5335e4b17023SJohn Marino
5336e4b17023SJohn Marino if (sets[i].rtl != 0 && dest != SET_DEST (sets[i].rtl))
5337e4b17023SJohn Marino sets[i].dest_hash = HASH (SET_DEST (sets[i].rtl), mode);
5338e4b17023SJohn Marino
5339e4b17023SJohn Marino #ifdef HAVE_cc0
5340e4b17023SJohn Marino /* If setting CC0, record what it was set to, or a constant, if it
5341e4b17023SJohn Marino is equivalent to a constant. If it is being set to a floating-point
5342e4b17023SJohn Marino value, make a COMPARE with the appropriate constant of 0. If we
5343e4b17023SJohn Marino don't do this, later code can interpret this as a test against
5344e4b17023SJohn Marino const0_rtx, which can cause problems if we try to put it into an
5345e4b17023SJohn Marino insn as a floating-point operand. */
5346e4b17023SJohn Marino if (dest == cc0_rtx)
5347e4b17023SJohn Marino {
5348e4b17023SJohn Marino this_insn_cc0 = src_const && mode != VOIDmode ? src_const : src;
5349e4b17023SJohn Marino this_insn_cc0_mode = mode;
5350e4b17023SJohn Marino if (FLOAT_MODE_P (mode))
5351e4b17023SJohn Marino this_insn_cc0 = gen_rtx_COMPARE (VOIDmode, this_insn_cc0,
5352e4b17023SJohn Marino CONST0_RTX (mode));
5353e4b17023SJohn Marino }
5354e4b17023SJohn Marino #endif
5355e4b17023SJohn Marino }
5356e4b17023SJohn Marino
5357e4b17023SJohn Marino /* Now enter all non-volatile source expressions in the hash table
5358e4b17023SJohn Marino if they are not already present.
5359e4b17023SJohn Marino Record their equivalence classes in src_elt.
5360e4b17023SJohn Marino This way we can insert the corresponding destinations into
5361e4b17023SJohn Marino the same classes even if the actual sources are no longer in them
5362e4b17023SJohn Marino (having been invalidated). */
5363e4b17023SJohn Marino
5364e4b17023SJohn Marino if (src_eqv && src_eqv_elt == 0 && sets[0].rtl != 0 && ! src_eqv_volatile
5365e4b17023SJohn Marino && ! rtx_equal_p (src_eqv, SET_DEST (sets[0].rtl)))
5366e4b17023SJohn Marino {
5367e4b17023SJohn Marino struct table_elt *elt;
5368e4b17023SJohn Marino struct table_elt *classp = sets[0].src_elt;
5369e4b17023SJohn Marino rtx dest = SET_DEST (sets[0].rtl);
5370e4b17023SJohn Marino enum machine_mode eqvmode = GET_MODE (dest);
5371e4b17023SJohn Marino
5372e4b17023SJohn Marino if (GET_CODE (dest) == STRICT_LOW_PART)
5373e4b17023SJohn Marino {
5374e4b17023SJohn Marino eqvmode = GET_MODE (SUBREG_REG (XEXP (dest, 0)));
5375e4b17023SJohn Marino classp = 0;
5376e4b17023SJohn Marino }
5377e4b17023SJohn Marino if (insert_regs (src_eqv, classp, 0))
5378e4b17023SJohn Marino {
5379e4b17023SJohn Marino rehash_using_reg (src_eqv);
5380e4b17023SJohn Marino src_eqv_hash = HASH (src_eqv, eqvmode);
5381e4b17023SJohn Marino }
5382e4b17023SJohn Marino elt = insert (src_eqv, classp, src_eqv_hash, eqvmode);
5383e4b17023SJohn Marino elt->in_memory = src_eqv_in_memory;
5384e4b17023SJohn Marino src_eqv_elt = elt;
5385e4b17023SJohn Marino
5386e4b17023SJohn Marino /* Check to see if src_eqv_elt is the same as a set source which
5387e4b17023SJohn Marino does not yet have an elt, and if so set the elt of the set source
5388e4b17023SJohn Marino to src_eqv_elt. */
5389e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
5390e4b17023SJohn Marino if (sets[i].rtl && sets[i].src_elt == 0
5391e4b17023SJohn Marino && rtx_equal_p (SET_SRC (sets[i].rtl), src_eqv))
5392e4b17023SJohn Marino sets[i].src_elt = src_eqv_elt;
5393e4b17023SJohn Marino }
5394e4b17023SJohn Marino
5395e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
5396e4b17023SJohn Marino if (sets[i].rtl && ! sets[i].src_volatile
5397e4b17023SJohn Marino && ! rtx_equal_p (SET_SRC (sets[i].rtl), SET_DEST (sets[i].rtl)))
5398e4b17023SJohn Marino {
5399e4b17023SJohn Marino if (GET_CODE (SET_DEST (sets[i].rtl)) == STRICT_LOW_PART)
5400e4b17023SJohn Marino {
5401e4b17023SJohn Marino /* REG_EQUAL in setting a STRICT_LOW_PART
5402e4b17023SJohn Marino gives an equivalent for the entire destination register,
5403e4b17023SJohn Marino not just for the subreg being stored in now.
5404e4b17023SJohn Marino This is a more interesting equivalence, so we arrange later
5405e4b17023SJohn Marino to treat the entire reg as the destination. */
5406e4b17023SJohn Marino sets[i].src_elt = src_eqv_elt;
5407e4b17023SJohn Marino sets[i].src_hash = src_eqv_hash;
5408e4b17023SJohn Marino }
5409e4b17023SJohn Marino else
5410e4b17023SJohn Marino {
5411e4b17023SJohn Marino /* Insert source and constant equivalent into hash table, if not
5412e4b17023SJohn Marino already present. */
5413e4b17023SJohn Marino struct table_elt *classp = src_eqv_elt;
5414e4b17023SJohn Marino rtx src = sets[i].src;
5415e4b17023SJohn Marino rtx dest = SET_DEST (sets[i].rtl);
5416e4b17023SJohn Marino enum machine_mode mode
5417e4b17023SJohn Marino = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
5418e4b17023SJohn Marino
5419e4b17023SJohn Marino /* It's possible that we have a source value known to be
5420e4b17023SJohn Marino constant but don't have a REG_EQUAL note on the insn.
5421e4b17023SJohn Marino Lack of a note will mean src_eqv_elt will be NULL. This
5422e4b17023SJohn Marino can happen where we've generated a SUBREG to access a
5423e4b17023SJohn Marino CONST_INT that is already in a register in a wider mode.
5424e4b17023SJohn Marino Ensure that the source expression is put in the proper
5425e4b17023SJohn Marino constant class. */
5426e4b17023SJohn Marino if (!classp)
5427e4b17023SJohn Marino classp = sets[i].src_const_elt;
5428e4b17023SJohn Marino
5429e4b17023SJohn Marino if (sets[i].src_elt == 0)
5430e4b17023SJohn Marino {
5431e4b17023SJohn Marino struct table_elt *elt;
5432e4b17023SJohn Marino
5433e4b17023SJohn Marino /* Note that these insert_regs calls cannot remove
5434e4b17023SJohn Marino any of the src_elt's, because they would have failed to
5435e4b17023SJohn Marino match if not still valid. */
5436e4b17023SJohn Marino if (insert_regs (src, classp, 0))
5437e4b17023SJohn Marino {
5438e4b17023SJohn Marino rehash_using_reg (src);
5439e4b17023SJohn Marino sets[i].src_hash = HASH (src, mode);
5440e4b17023SJohn Marino }
5441e4b17023SJohn Marino elt = insert (src, classp, sets[i].src_hash, mode);
5442e4b17023SJohn Marino elt->in_memory = sets[i].src_in_memory;
5443e4b17023SJohn Marino sets[i].src_elt = classp = elt;
5444e4b17023SJohn Marino }
5445e4b17023SJohn Marino if (sets[i].src_const && sets[i].src_const_elt == 0
5446e4b17023SJohn Marino && src != sets[i].src_const
5447e4b17023SJohn Marino && ! rtx_equal_p (sets[i].src_const, src))
5448e4b17023SJohn Marino sets[i].src_elt = insert (sets[i].src_const, classp,
5449e4b17023SJohn Marino sets[i].src_const_hash, mode);
5450e4b17023SJohn Marino }
5451e4b17023SJohn Marino }
5452e4b17023SJohn Marino else if (sets[i].src_elt == 0)
5453e4b17023SJohn Marino /* If we did not insert the source into the hash table (e.g., it was
5454e4b17023SJohn Marino volatile), note the equivalence class for the REG_EQUAL value, if any,
5455e4b17023SJohn Marino so that the destination goes into that class. */
5456e4b17023SJohn Marino sets[i].src_elt = src_eqv_elt;
5457e4b17023SJohn Marino
5458e4b17023SJohn Marino /* Record destination addresses in the hash table. This allows us to
5459e4b17023SJohn Marino check if they are invalidated by other sets. */
5460e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
5461e4b17023SJohn Marino {
5462e4b17023SJohn Marino if (sets[i].rtl)
5463e4b17023SJohn Marino {
5464e4b17023SJohn Marino rtx x = sets[i].inner_dest;
5465e4b17023SJohn Marino struct table_elt *elt;
5466e4b17023SJohn Marino enum machine_mode mode;
5467e4b17023SJohn Marino unsigned hash;
5468e4b17023SJohn Marino
5469e4b17023SJohn Marino if (MEM_P (x))
5470e4b17023SJohn Marino {
5471e4b17023SJohn Marino x = XEXP (x, 0);
5472e4b17023SJohn Marino mode = GET_MODE (x);
5473e4b17023SJohn Marino hash = HASH (x, mode);
5474e4b17023SJohn Marino elt = lookup (x, hash, mode);
5475e4b17023SJohn Marino if (!elt)
5476e4b17023SJohn Marino {
5477e4b17023SJohn Marino if (insert_regs (x, NULL, 0))
5478e4b17023SJohn Marino {
5479e4b17023SJohn Marino rtx dest = SET_DEST (sets[i].rtl);
5480e4b17023SJohn Marino
5481e4b17023SJohn Marino rehash_using_reg (x);
5482e4b17023SJohn Marino hash = HASH (x, mode);
5483e4b17023SJohn Marino sets[i].dest_hash = HASH (dest, GET_MODE (dest));
5484e4b17023SJohn Marino }
5485e4b17023SJohn Marino elt = insert (x, NULL, hash, mode);
5486e4b17023SJohn Marino }
5487e4b17023SJohn Marino
5488e4b17023SJohn Marino sets[i].dest_addr_elt = elt;
5489e4b17023SJohn Marino }
5490e4b17023SJohn Marino else
5491e4b17023SJohn Marino sets[i].dest_addr_elt = NULL;
5492e4b17023SJohn Marino }
5493e4b17023SJohn Marino }
5494e4b17023SJohn Marino
5495e4b17023SJohn Marino invalidate_from_clobbers (x);
5496e4b17023SJohn Marino
5497e4b17023SJohn Marino /* Some registers are invalidated by subroutine calls. Memory is
5498e4b17023SJohn Marino invalidated by non-constant calls. */
5499e4b17023SJohn Marino
5500e4b17023SJohn Marino if (CALL_P (insn))
5501e4b17023SJohn Marino {
5502e4b17023SJohn Marino if (!(RTL_CONST_OR_PURE_CALL_P (insn)))
5503e4b17023SJohn Marino invalidate_memory ();
5504e4b17023SJohn Marino invalidate_for_call ();
5505e4b17023SJohn Marino }
5506e4b17023SJohn Marino
5507e4b17023SJohn Marino /* Now invalidate everything set by this instruction.
5508e4b17023SJohn Marino If a SUBREG or other funny destination is being set,
5509e4b17023SJohn Marino sets[i].rtl is still nonzero, so here we invalidate the reg
5510e4b17023SJohn Marino a part of which is being set. */
5511e4b17023SJohn Marino
5512e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
5513e4b17023SJohn Marino if (sets[i].rtl)
5514e4b17023SJohn Marino {
5515e4b17023SJohn Marino /* We can't use the inner dest, because the mode associated with
5516e4b17023SJohn Marino a ZERO_EXTRACT is significant. */
5517e4b17023SJohn Marino rtx dest = SET_DEST (sets[i].rtl);
5518e4b17023SJohn Marino
5519e4b17023SJohn Marino /* Needed for registers to remove the register from its
5520e4b17023SJohn Marino previous quantity's chain.
5521e4b17023SJohn Marino Needed for memory if this is a nonvarying address, unless
5522e4b17023SJohn Marino we have just done an invalidate_memory that covers even those. */
5523e4b17023SJohn Marino if (REG_P (dest) || GET_CODE (dest) == SUBREG)
5524e4b17023SJohn Marino invalidate (dest, VOIDmode);
5525e4b17023SJohn Marino else if (MEM_P (dest))
5526e4b17023SJohn Marino invalidate (dest, VOIDmode);
5527e4b17023SJohn Marino else if (GET_CODE (dest) == STRICT_LOW_PART
5528e4b17023SJohn Marino || GET_CODE (dest) == ZERO_EXTRACT)
5529e4b17023SJohn Marino invalidate (XEXP (dest, 0), GET_MODE (dest));
5530e4b17023SJohn Marino }
5531e4b17023SJohn Marino
5532e4b17023SJohn Marino /* A volatile ASM invalidates everything. */
5533e4b17023SJohn Marino if (NONJUMP_INSN_P (insn)
5534e4b17023SJohn Marino && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
5535e4b17023SJohn Marino && MEM_VOLATILE_P (PATTERN (insn)))
5536e4b17023SJohn Marino flush_hash_table ();
5537e4b17023SJohn Marino
5538e4b17023SJohn Marino /* Don't cse over a call to setjmp; on some machines (eg VAX)
5539e4b17023SJohn Marino the regs restored by the longjmp come from a later time
5540e4b17023SJohn Marino than the setjmp. */
5541e4b17023SJohn Marino if (CALL_P (insn) && find_reg_note (insn, REG_SETJMP, NULL))
5542e4b17023SJohn Marino {
5543e4b17023SJohn Marino flush_hash_table ();
5544e4b17023SJohn Marino goto done;
5545e4b17023SJohn Marino }
5546e4b17023SJohn Marino
5547e4b17023SJohn Marino /* Make sure registers mentioned in destinations
5548e4b17023SJohn Marino are safe for use in an expression to be inserted.
5549e4b17023SJohn Marino This removes from the hash table
5550e4b17023SJohn Marino any invalid entry that refers to one of these registers.
5551e4b17023SJohn Marino
5552e4b17023SJohn Marino We don't care about the return value from mention_regs because
5553e4b17023SJohn Marino we are going to hash the SET_DEST values unconditionally. */
5554e4b17023SJohn Marino
5555e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
5556e4b17023SJohn Marino {
5557e4b17023SJohn Marino if (sets[i].rtl)
5558e4b17023SJohn Marino {
5559e4b17023SJohn Marino rtx x = SET_DEST (sets[i].rtl);
5560e4b17023SJohn Marino
5561e4b17023SJohn Marino if (!REG_P (x))
5562e4b17023SJohn Marino mention_regs (x);
5563e4b17023SJohn Marino else
5564e4b17023SJohn Marino {
5565e4b17023SJohn Marino /* We used to rely on all references to a register becoming
5566e4b17023SJohn Marino inaccessible when a register changes to a new quantity,
5567e4b17023SJohn Marino since that changes the hash code. However, that is not
5568e4b17023SJohn Marino safe, since after HASH_SIZE new quantities we get a
5569e4b17023SJohn Marino hash 'collision' of a register with its own invalid
5570e4b17023SJohn Marino entries. And since SUBREGs have been changed not to
5571e4b17023SJohn Marino change their hash code with the hash code of the register,
5572e4b17023SJohn Marino it wouldn't work any longer at all. So we have to check
5573e4b17023SJohn Marino for any invalid references lying around now.
5574e4b17023SJohn Marino This code is similar to the REG case in mention_regs,
5575e4b17023SJohn Marino but it knows that reg_tick has been incremented, and
5576e4b17023SJohn Marino it leaves reg_in_table as -1 . */
5577e4b17023SJohn Marino unsigned int regno = REGNO (x);
5578e4b17023SJohn Marino unsigned int endregno = END_REGNO (x);
5579e4b17023SJohn Marino unsigned int i;
5580e4b17023SJohn Marino
5581e4b17023SJohn Marino for (i = regno; i < endregno; i++)
5582e4b17023SJohn Marino {
5583e4b17023SJohn Marino if (REG_IN_TABLE (i) >= 0)
5584e4b17023SJohn Marino {
5585e4b17023SJohn Marino remove_invalid_refs (i);
5586e4b17023SJohn Marino REG_IN_TABLE (i) = -1;
5587e4b17023SJohn Marino }
5588e4b17023SJohn Marino }
5589e4b17023SJohn Marino }
5590e4b17023SJohn Marino }
5591e4b17023SJohn Marino }
5592e4b17023SJohn Marino
5593e4b17023SJohn Marino /* We may have just removed some of the src_elt's from the hash table.
5594e4b17023SJohn Marino So replace each one with the current head of the same class.
5595e4b17023SJohn Marino Also check if destination addresses have been removed. */
5596e4b17023SJohn Marino
5597e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
5598e4b17023SJohn Marino if (sets[i].rtl)
5599e4b17023SJohn Marino {
5600e4b17023SJohn Marino if (sets[i].dest_addr_elt
5601e4b17023SJohn Marino && sets[i].dest_addr_elt->first_same_value == 0)
5602e4b17023SJohn Marino {
5603e4b17023SJohn Marino /* The elt was removed, which means this destination is not
5604e4b17023SJohn Marino valid after this instruction. */
5605e4b17023SJohn Marino sets[i].rtl = NULL_RTX;
5606e4b17023SJohn Marino }
5607e4b17023SJohn Marino else if (sets[i].src_elt && sets[i].src_elt->first_same_value == 0)
5608e4b17023SJohn Marino /* If elt was removed, find current head of same class,
5609e4b17023SJohn Marino or 0 if nothing remains of that class. */
5610e4b17023SJohn Marino {
5611e4b17023SJohn Marino struct table_elt *elt = sets[i].src_elt;
5612e4b17023SJohn Marino
5613e4b17023SJohn Marino while (elt && elt->prev_same_value)
5614e4b17023SJohn Marino elt = elt->prev_same_value;
5615e4b17023SJohn Marino
5616e4b17023SJohn Marino while (elt && elt->first_same_value == 0)
5617e4b17023SJohn Marino elt = elt->next_same_value;
5618e4b17023SJohn Marino sets[i].src_elt = elt ? elt->first_same_value : 0;
5619e4b17023SJohn Marino }
5620e4b17023SJohn Marino }
5621e4b17023SJohn Marino
5622e4b17023SJohn Marino /* Now insert the destinations into their equivalence classes. */
5623e4b17023SJohn Marino
5624e4b17023SJohn Marino for (i = 0; i < n_sets; i++)
5625e4b17023SJohn Marino if (sets[i].rtl)
5626e4b17023SJohn Marino {
5627e4b17023SJohn Marino rtx dest = SET_DEST (sets[i].rtl);
5628e4b17023SJohn Marino struct table_elt *elt;
5629e4b17023SJohn Marino
5630e4b17023SJohn Marino /* Don't record value if we are not supposed to risk allocating
5631e4b17023SJohn Marino floating-point values in registers that might be wider than
5632e4b17023SJohn Marino memory. */
5633e4b17023SJohn Marino if ((flag_float_store
5634e4b17023SJohn Marino && MEM_P (dest)
5635e4b17023SJohn Marino && FLOAT_MODE_P (GET_MODE (dest)))
5636e4b17023SJohn Marino /* Don't record BLKmode values, because we don't know the
5637e4b17023SJohn Marino size of it, and can't be sure that other BLKmode values
5638e4b17023SJohn Marino have the same or smaller size. */
5639e4b17023SJohn Marino || GET_MODE (dest) == BLKmode
5640e4b17023SJohn Marino /* If we didn't put a REG_EQUAL value or a source into the hash
5641e4b17023SJohn Marino table, there is no point is recording DEST. */
5642e4b17023SJohn Marino || sets[i].src_elt == 0
5643e4b17023SJohn Marino /* If DEST is a paradoxical SUBREG and SRC is a ZERO_EXTEND
5644e4b17023SJohn Marino or SIGN_EXTEND, don't record DEST since it can cause
5645e4b17023SJohn Marino some tracking to be wrong.
5646e4b17023SJohn Marino
5647e4b17023SJohn Marino ??? Think about this more later. */
5648e4b17023SJohn Marino || (paradoxical_subreg_p (dest)
5649e4b17023SJohn Marino && (GET_CODE (sets[i].src) == SIGN_EXTEND
5650e4b17023SJohn Marino || GET_CODE (sets[i].src) == ZERO_EXTEND)))
5651e4b17023SJohn Marino continue;
5652e4b17023SJohn Marino
5653e4b17023SJohn Marino /* STRICT_LOW_PART isn't part of the value BEING set,
5654e4b17023SJohn Marino and neither is the SUBREG inside it.
5655e4b17023SJohn Marino Note that in this case SETS[I].SRC_ELT is really SRC_EQV_ELT. */
5656e4b17023SJohn Marino if (GET_CODE (dest) == STRICT_LOW_PART)
5657e4b17023SJohn Marino dest = SUBREG_REG (XEXP (dest, 0));
5658e4b17023SJohn Marino
5659e4b17023SJohn Marino if (REG_P (dest) || GET_CODE (dest) == SUBREG)
5660e4b17023SJohn Marino /* Registers must also be inserted into chains for quantities. */
5661e4b17023SJohn Marino if (insert_regs (dest, sets[i].src_elt, 1))
5662e4b17023SJohn Marino {
5663e4b17023SJohn Marino /* If `insert_regs' changes something, the hash code must be
5664e4b17023SJohn Marino recalculated. */
5665e4b17023SJohn Marino rehash_using_reg (dest);
5666e4b17023SJohn Marino sets[i].dest_hash = HASH (dest, GET_MODE (dest));
5667e4b17023SJohn Marino }
5668e4b17023SJohn Marino
5669e4b17023SJohn Marino elt = insert (dest, sets[i].src_elt,
5670e4b17023SJohn Marino sets[i].dest_hash, GET_MODE (dest));
5671e4b17023SJohn Marino
5672e4b17023SJohn Marino /* If this is a constant, insert the constant anchors with the
5673e4b17023SJohn Marino equivalent register-offset expressions using register DEST. */
5674e4b17023SJohn Marino if (targetm.const_anchor
5675e4b17023SJohn Marino && REG_P (dest)
5676e4b17023SJohn Marino && SCALAR_INT_MODE_P (GET_MODE (dest))
5677e4b17023SJohn Marino && GET_CODE (sets[i].src_elt->exp) == CONST_INT)
5678e4b17023SJohn Marino insert_const_anchors (dest, sets[i].src_elt->exp, GET_MODE (dest));
5679e4b17023SJohn Marino
5680e4b17023SJohn Marino elt->in_memory = (MEM_P (sets[i].inner_dest)
5681e4b17023SJohn Marino && !MEM_READONLY_P (sets[i].inner_dest));
5682e4b17023SJohn Marino
5683e4b17023SJohn Marino /* If we have (set (subreg:m1 (reg:m2 foo) 0) (bar:m1)), M1 is no
5684e4b17023SJohn Marino narrower than M2, and both M1 and M2 are the same number of words,
5685e4b17023SJohn Marino we are also doing (set (reg:m2 foo) (subreg:m2 (bar:m1) 0)) so
5686e4b17023SJohn Marino make that equivalence as well.
5687e4b17023SJohn Marino
5688e4b17023SJohn Marino However, BAR may have equivalences for which gen_lowpart
5689e4b17023SJohn Marino will produce a simpler value than gen_lowpart applied to
5690e4b17023SJohn Marino BAR (e.g., if BAR was ZERO_EXTENDed from M2), so we will scan all
5691e4b17023SJohn Marino BAR's equivalences. If we don't get a simplified form, make
5692e4b17023SJohn Marino the SUBREG. It will not be used in an equivalence, but will
5693e4b17023SJohn Marino cause two similar assignments to be detected.
5694e4b17023SJohn Marino
5695e4b17023SJohn Marino Note the loop below will find SUBREG_REG (DEST) since we have
5696e4b17023SJohn Marino already entered SRC and DEST of the SET in the table. */
5697e4b17023SJohn Marino
5698e4b17023SJohn Marino if (GET_CODE (dest) == SUBREG
5699e4b17023SJohn Marino && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) - 1)
5700e4b17023SJohn Marino / UNITS_PER_WORD)
5701e4b17023SJohn Marino == (GET_MODE_SIZE (GET_MODE (dest)) - 1) / UNITS_PER_WORD)
5702e4b17023SJohn Marino && (GET_MODE_SIZE (GET_MODE (dest))
5703e4b17023SJohn Marino >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
5704e4b17023SJohn Marino && sets[i].src_elt != 0)
5705e4b17023SJohn Marino {
5706e4b17023SJohn Marino enum machine_mode new_mode = GET_MODE (SUBREG_REG (dest));
5707e4b17023SJohn Marino struct table_elt *elt, *classp = 0;
5708e4b17023SJohn Marino
5709e4b17023SJohn Marino for (elt = sets[i].src_elt->first_same_value; elt;
5710e4b17023SJohn Marino elt = elt->next_same_value)
5711e4b17023SJohn Marino {
5712e4b17023SJohn Marino rtx new_src = 0;
5713e4b17023SJohn Marino unsigned src_hash;
5714e4b17023SJohn Marino struct table_elt *src_elt;
5715e4b17023SJohn Marino int byte = 0;
5716e4b17023SJohn Marino
5717e4b17023SJohn Marino /* Ignore invalid entries. */
5718e4b17023SJohn Marino if (!REG_P (elt->exp)
5719e4b17023SJohn Marino && ! exp_equiv_p (elt->exp, elt->exp, 1, false))
5720e4b17023SJohn Marino continue;
5721e4b17023SJohn Marino
5722e4b17023SJohn Marino /* We may have already been playing subreg games. If the
5723e4b17023SJohn Marino mode is already correct for the destination, use it. */
5724e4b17023SJohn Marino if (GET_MODE (elt->exp) == new_mode)
5725e4b17023SJohn Marino new_src = elt->exp;
5726e4b17023SJohn Marino else
5727e4b17023SJohn Marino {
5728e4b17023SJohn Marino /* Calculate big endian correction for the SUBREG_BYTE.
5729e4b17023SJohn Marino We have already checked that M1 (GET_MODE (dest))
5730e4b17023SJohn Marino is not narrower than M2 (new_mode). */
5731e4b17023SJohn Marino if (BYTES_BIG_ENDIAN)
5732e4b17023SJohn Marino byte = (GET_MODE_SIZE (GET_MODE (dest))
5733e4b17023SJohn Marino - GET_MODE_SIZE (new_mode));
5734e4b17023SJohn Marino
5735e4b17023SJohn Marino new_src = simplify_gen_subreg (new_mode, elt->exp,
5736e4b17023SJohn Marino GET_MODE (dest), byte);
5737e4b17023SJohn Marino }
5738e4b17023SJohn Marino
5739e4b17023SJohn Marino /* The call to simplify_gen_subreg fails if the value
5740e4b17023SJohn Marino is VOIDmode, yet we can't do any simplification, e.g.
5741e4b17023SJohn Marino for EXPR_LISTs denoting function call results.
5742e4b17023SJohn Marino It is invalid to construct a SUBREG with a VOIDmode
5743e4b17023SJohn Marino SUBREG_REG, hence a zero new_src means we can't do
5744e4b17023SJohn Marino this substitution. */
5745e4b17023SJohn Marino if (! new_src)
5746e4b17023SJohn Marino continue;
5747e4b17023SJohn Marino
5748e4b17023SJohn Marino src_hash = HASH (new_src, new_mode);
5749e4b17023SJohn Marino src_elt = lookup (new_src, src_hash, new_mode);
5750e4b17023SJohn Marino
5751e4b17023SJohn Marino /* Put the new source in the hash table is if isn't
5752e4b17023SJohn Marino already. */
5753e4b17023SJohn Marino if (src_elt == 0)
5754e4b17023SJohn Marino {
5755e4b17023SJohn Marino if (insert_regs (new_src, classp, 0))
5756e4b17023SJohn Marino {
5757e4b17023SJohn Marino rehash_using_reg (new_src);
5758e4b17023SJohn Marino src_hash = HASH (new_src, new_mode);
5759e4b17023SJohn Marino }
5760e4b17023SJohn Marino src_elt = insert (new_src, classp, src_hash, new_mode);
5761e4b17023SJohn Marino src_elt->in_memory = elt->in_memory;
5762e4b17023SJohn Marino }
5763e4b17023SJohn Marino else if (classp && classp != src_elt->first_same_value)
5764e4b17023SJohn Marino /* Show that two things that we've seen before are
5765e4b17023SJohn Marino actually the same. */
5766e4b17023SJohn Marino merge_equiv_classes (src_elt, classp);
5767e4b17023SJohn Marino
5768e4b17023SJohn Marino classp = src_elt->first_same_value;
5769e4b17023SJohn Marino /* Ignore invalid entries. */
5770e4b17023SJohn Marino while (classp
5771e4b17023SJohn Marino && !REG_P (classp->exp)
5772e4b17023SJohn Marino && ! exp_equiv_p (classp->exp, classp->exp, 1, false))
5773e4b17023SJohn Marino classp = classp->next_same_value;
5774e4b17023SJohn Marino }
5775e4b17023SJohn Marino }
5776e4b17023SJohn Marino }
5777e4b17023SJohn Marino
5778e4b17023SJohn Marino /* Special handling for (set REG0 REG1) where REG0 is the
5779e4b17023SJohn Marino "cheapest", cheaper than REG1. After cse, REG1 will probably not
5780e4b17023SJohn Marino be used in the sequel, so (if easily done) change this insn to
5781e4b17023SJohn Marino (set REG1 REG0) and replace REG1 with REG0 in the previous insn
5782e4b17023SJohn Marino that computed their value. Then REG1 will become a dead store
5783e4b17023SJohn Marino and won't cloud the situation for later optimizations.
5784e4b17023SJohn Marino
5785e4b17023SJohn Marino Do not make this change if REG1 is a hard register, because it will
5786e4b17023SJohn Marino then be used in the sequel and we may be changing a two-operand insn
5787e4b17023SJohn Marino into a three-operand insn.
5788e4b17023SJohn Marino
5789e4b17023SJohn Marino Also do not do this if we are operating on a copy of INSN. */
5790e4b17023SJohn Marino
5791e4b17023SJohn Marino if (n_sets == 1 && sets[0].rtl && REG_P (SET_DEST (sets[0].rtl))
5792e4b17023SJohn Marino && NEXT_INSN (PREV_INSN (insn)) == insn
5793e4b17023SJohn Marino && REG_P (SET_SRC (sets[0].rtl))
5794e4b17023SJohn Marino && REGNO (SET_SRC (sets[0].rtl)) >= FIRST_PSEUDO_REGISTER
5795e4b17023SJohn Marino && REGNO_QTY_VALID_P (REGNO (SET_SRC (sets[0].rtl))))
5796e4b17023SJohn Marino {
5797e4b17023SJohn Marino int src_q = REG_QTY (REGNO (SET_SRC (sets[0].rtl)));
5798e4b17023SJohn Marino struct qty_table_elem *src_ent = &qty_table[src_q];
5799e4b17023SJohn Marino
5800e4b17023SJohn Marino if (src_ent->first_reg == REGNO (SET_DEST (sets[0].rtl)))
5801e4b17023SJohn Marino {
5802e4b17023SJohn Marino /* Scan for the previous nonnote insn, but stop at a basic
5803e4b17023SJohn Marino block boundary. */
5804e4b17023SJohn Marino rtx prev = insn;
5805e4b17023SJohn Marino rtx bb_head = BB_HEAD (BLOCK_FOR_INSN (insn));
5806e4b17023SJohn Marino do
5807e4b17023SJohn Marino {
5808e4b17023SJohn Marino prev = PREV_INSN (prev);
5809e4b17023SJohn Marino }
5810e4b17023SJohn Marino while (prev != bb_head && (NOTE_P (prev) || DEBUG_INSN_P (prev)));
5811e4b17023SJohn Marino
5812e4b17023SJohn Marino /* Do not swap the registers around if the previous instruction
5813e4b17023SJohn Marino attaches a REG_EQUIV note to REG1.
5814e4b17023SJohn Marino
5815e4b17023SJohn Marino ??? It's not entirely clear whether we can transfer a REG_EQUIV
5816e4b17023SJohn Marino from the pseudo that originally shadowed an incoming argument
5817e4b17023SJohn Marino to another register. Some uses of REG_EQUIV might rely on it
5818e4b17023SJohn Marino being attached to REG1 rather than REG2.
5819e4b17023SJohn Marino
5820e4b17023SJohn Marino This section previously turned the REG_EQUIV into a REG_EQUAL
5821e4b17023SJohn Marino note. We cannot do that because REG_EQUIV may provide an
5822e4b17023SJohn Marino uninitialized stack slot when REG_PARM_STACK_SPACE is used. */
5823e4b17023SJohn Marino if (NONJUMP_INSN_P (prev)
5824e4b17023SJohn Marino && GET_CODE (PATTERN (prev)) == SET
5825e4b17023SJohn Marino && SET_DEST (PATTERN (prev)) == SET_SRC (sets[0].rtl)
5826e4b17023SJohn Marino && ! find_reg_note (prev, REG_EQUIV, NULL_RTX))
5827e4b17023SJohn Marino {
5828e4b17023SJohn Marino rtx dest = SET_DEST (sets[0].rtl);
5829e4b17023SJohn Marino rtx src = SET_SRC (sets[0].rtl);
5830e4b17023SJohn Marino rtx note;
5831e4b17023SJohn Marino
5832e4b17023SJohn Marino validate_change (prev, &SET_DEST (PATTERN (prev)), dest, 1);
5833e4b17023SJohn Marino validate_change (insn, &SET_DEST (sets[0].rtl), src, 1);
5834e4b17023SJohn Marino validate_change (insn, &SET_SRC (sets[0].rtl), dest, 1);
5835e4b17023SJohn Marino apply_change_group ();
5836e4b17023SJohn Marino
5837e4b17023SJohn Marino /* If INSN has a REG_EQUAL note, and this note mentions
5838e4b17023SJohn Marino REG0, then we must delete it, because the value in
5839e4b17023SJohn Marino REG0 has changed. If the note's value is REG1, we must
5840e4b17023SJohn Marino also delete it because that is now this insn's dest. */
5841e4b17023SJohn Marino note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
5842e4b17023SJohn Marino if (note != 0
5843e4b17023SJohn Marino && (reg_mentioned_p (dest, XEXP (note, 0))
5844e4b17023SJohn Marino || rtx_equal_p (src, XEXP (note, 0))))
5845e4b17023SJohn Marino remove_note (insn, note);
5846e4b17023SJohn Marino }
5847e4b17023SJohn Marino }
5848e4b17023SJohn Marino }
5849e4b17023SJohn Marino
5850e4b17023SJohn Marino done:;
5851e4b17023SJohn Marino }
5852e4b17023SJohn Marino
5853e4b17023SJohn Marino /* Remove from the hash table all expressions that reference memory. */
5854e4b17023SJohn Marino
5855e4b17023SJohn Marino static void
invalidate_memory(void)5856e4b17023SJohn Marino invalidate_memory (void)
5857e4b17023SJohn Marino {
5858e4b17023SJohn Marino int i;
5859e4b17023SJohn Marino struct table_elt *p, *next;
5860e4b17023SJohn Marino
5861e4b17023SJohn Marino for (i = 0; i < HASH_SIZE; i++)
5862e4b17023SJohn Marino for (p = table[i]; p; p = next)
5863e4b17023SJohn Marino {
5864e4b17023SJohn Marino next = p->next_same_hash;
5865e4b17023SJohn Marino if (p->in_memory)
5866e4b17023SJohn Marino remove_from_table (p, i);
5867e4b17023SJohn Marino }
5868e4b17023SJohn Marino }
5869e4b17023SJohn Marino
5870e4b17023SJohn Marino /* Perform invalidation on the basis of everything about an insn
5871e4b17023SJohn Marino except for invalidating the actual places that are SET in it.
5872e4b17023SJohn Marino This includes the places CLOBBERed, and anything that might
5873e4b17023SJohn Marino alias with something that is SET or CLOBBERed.
5874e4b17023SJohn Marino
5875e4b17023SJohn Marino X is the pattern of the insn. */
5876e4b17023SJohn Marino
5877e4b17023SJohn Marino static void
invalidate_from_clobbers(rtx x)5878e4b17023SJohn Marino invalidate_from_clobbers (rtx x)
5879e4b17023SJohn Marino {
5880e4b17023SJohn Marino if (GET_CODE (x) == CLOBBER)
5881e4b17023SJohn Marino {
5882e4b17023SJohn Marino rtx ref = XEXP (x, 0);
5883e4b17023SJohn Marino if (ref)
5884e4b17023SJohn Marino {
5885e4b17023SJohn Marino if (REG_P (ref) || GET_CODE (ref) == SUBREG
5886e4b17023SJohn Marino || MEM_P (ref))
5887e4b17023SJohn Marino invalidate (ref, VOIDmode);
5888e4b17023SJohn Marino else if (GET_CODE (ref) == STRICT_LOW_PART
5889e4b17023SJohn Marino || GET_CODE (ref) == ZERO_EXTRACT)
5890e4b17023SJohn Marino invalidate (XEXP (ref, 0), GET_MODE (ref));
5891e4b17023SJohn Marino }
5892e4b17023SJohn Marino }
5893e4b17023SJohn Marino else if (GET_CODE (x) == PARALLEL)
5894e4b17023SJohn Marino {
5895e4b17023SJohn Marino int i;
5896e4b17023SJohn Marino for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
5897e4b17023SJohn Marino {
5898e4b17023SJohn Marino rtx y = XVECEXP (x, 0, i);
5899e4b17023SJohn Marino if (GET_CODE (y) == CLOBBER)
5900e4b17023SJohn Marino {
5901e4b17023SJohn Marino rtx ref = XEXP (y, 0);
5902e4b17023SJohn Marino if (REG_P (ref) || GET_CODE (ref) == SUBREG
5903e4b17023SJohn Marino || MEM_P (ref))
5904e4b17023SJohn Marino invalidate (ref, VOIDmode);
5905e4b17023SJohn Marino else if (GET_CODE (ref) == STRICT_LOW_PART
5906e4b17023SJohn Marino || GET_CODE (ref) == ZERO_EXTRACT)
5907e4b17023SJohn Marino invalidate (XEXP (ref, 0), GET_MODE (ref));
5908e4b17023SJohn Marino }
5909e4b17023SJohn Marino }
5910e4b17023SJohn Marino }
5911e4b17023SJohn Marino }
5912e4b17023SJohn Marino
5913e4b17023SJohn Marino /* Process X, part of the REG_NOTES of an insn. Look at any REG_EQUAL notes
5914e4b17023SJohn Marino and replace any registers in them with either an equivalent constant
5915e4b17023SJohn Marino or the canonical form of the register. If we are inside an address,
5916e4b17023SJohn Marino only do this if the address remains valid.
5917e4b17023SJohn Marino
5918e4b17023SJohn Marino OBJECT is 0 except when within a MEM in which case it is the MEM.
5919e4b17023SJohn Marino
5920e4b17023SJohn Marino Return the replacement for X. */
5921e4b17023SJohn Marino
5922e4b17023SJohn Marino static rtx
cse_process_notes_1(rtx x,rtx object,bool * changed)5923e4b17023SJohn Marino cse_process_notes_1 (rtx x, rtx object, bool *changed)
5924e4b17023SJohn Marino {
5925e4b17023SJohn Marino enum rtx_code code = GET_CODE (x);
5926e4b17023SJohn Marino const char *fmt = GET_RTX_FORMAT (code);
5927e4b17023SJohn Marino int i;
5928e4b17023SJohn Marino
5929e4b17023SJohn Marino switch (code)
5930e4b17023SJohn Marino {
5931e4b17023SJohn Marino case CONST_INT:
5932e4b17023SJohn Marino case CONST:
5933e4b17023SJohn Marino case SYMBOL_REF:
5934e4b17023SJohn Marino case LABEL_REF:
5935e4b17023SJohn Marino case CONST_DOUBLE:
5936e4b17023SJohn Marino case CONST_FIXED:
5937e4b17023SJohn Marino case CONST_VECTOR:
5938e4b17023SJohn Marino case PC:
5939e4b17023SJohn Marino case CC0:
5940e4b17023SJohn Marino case LO_SUM:
5941e4b17023SJohn Marino return x;
5942e4b17023SJohn Marino
5943e4b17023SJohn Marino case MEM:
5944e4b17023SJohn Marino validate_change (x, &XEXP (x, 0),
5945e4b17023SJohn Marino cse_process_notes (XEXP (x, 0), x, changed), 0);
5946e4b17023SJohn Marino return x;
5947e4b17023SJohn Marino
5948e4b17023SJohn Marino case EXPR_LIST:
5949e4b17023SJohn Marino case INSN_LIST:
5950e4b17023SJohn Marino if (REG_NOTE_KIND (x) == REG_EQUAL)
5951e4b17023SJohn Marino XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX, changed);
5952e4b17023SJohn Marino if (XEXP (x, 1))
5953e4b17023SJohn Marino XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX, changed);
5954e4b17023SJohn Marino return x;
5955e4b17023SJohn Marino
5956e4b17023SJohn Marino case SIGN_EXTEND:
5957e4b17023SJohn Marino case ZERO_EXTEND:
5958e4b17023SJohn Marino case SUBREG:
5959e4b17023SJohn Marino {
5960e4b17023SJohn Marino rtx new_rtx = cse_process_notes (XEXP (x, 0), object, changed);
5961e4b17023SJohn Marino /* We don't substitute VOIDmode constants into these rtx,
5962e4b17023SJohn Marino since they would impede folding. */
5963e4b17023SJohn Marino if (GET_MODE (new_rtx) != VOIDmode)
5964e4b17023SJohn Marino validate_change (object, &XEXP (x, 0), new_rtx, 0);
5965e4b17023SJohn Marino return x;
5966e4b17023SJohn Marino }
5967e4b17023SJohn Marino
5968e4b17023SJohn Marino case REG:
5969e4b17023SJohn Marino i = REG_QTY (REGNO (x));
5970e4b17023SJohn Marino
5971e4b17023SJohn Marino /* Return a constant or a constant register. */
5972e4b17023SJohn Marino if (REGNO_QTY_VALID_P (REGNO (x)))
5973e4b17023SJohn Marino {
5974e4b17023SJohn Marino struct qty_table_elem *ent = &qty_table[i];
5975e4b17023SJohn Marino
5976e4b17023SJohn Marino if (ent->const_rtx != NULL_RTX
5977e4b17023SJohn Marino && (CONSTANT_P (ent->const_rtx)
5978e4b17023SJohn Marino || REG_P (ent->const_rtx)))
5979e4b17023SJohn Marino {
5980e4b17023SJohn Marino rtx new_rtx = gen_lowpart (GET_MODE (x), ent->const_rtx);
5981e4b17023SJohn Marino if (new_rtx)
5982e4b17023SJohn Marino return copy_rtx (new_rtx);
5983e4b17023SJohn Marino }
5984e4b17023SJohn Marino }
5985e4b17023SJohn Marino
5986e4b17023SJohn Marino /* Otherwise, canonicalize this register. */
5987e4b17023SJohn Marino return canon_reg (x, NULL_RTX);
5988e4b17023SJohn Marino
5989e4b17023SJohn Marino default:
5990e4b17023SJohn Marino break;
5991e4b17023SJohn Marino }
5992e4b17023SJohn Marino
5993e4b17023SJohn Marino for (i = 0; i < GET_RTX_LENGTH (code); i++)
5994e4b17023SJohn Marino if (fmt[i] == 'e')
5995e4b17023SJohn Marino validate_change (object, &XEXP (x, i),
5996e4b17023SJohn Marino cse_process_notes (XEXP (x, i), object, changed), 0);
5997e4b17023SJohn Marino
5998e4b17023SJohn Marino return x;
5999e4b17023SJohn Marino }
6000e4b17023SJohn Marino
6001e4b17023SJohn Marino static rtx
cse_process_notes(rtx x,rtx object,bool * changed)6002e4b17023SJohn Marino cse_process_notes (rtx x, rtx object, bool *changed)
6003e4b17023SJohn Marino {
6004e4b17023SJohn Marino rtx new_rtx = cse_process_notes_1 (x, object, changed);
6005e4b17023SJohn Marino if (new_rtx != x)
6006e4b17023SJohn Marino *changed = true;
6007e4b17023SJohn Marino return new_rtx;
6008e4b17023SJohn Marino }
6009e4b17023SJohn Marino
6010e4b17023SJohn Marino
6011e4b17023SJohn Marino /* Find a path in the CFG, starting with FIRST_BB to perform CSE on.
6012e4b17023SJohn Marino
6013e4b17023SJohn Marino DATA is a pointer to a struct cse_basic_block_data, that is used to
6014e4b17023SJohn Marino describe the path.
6015e4b17023SJohn Marino It is filled with a queue of basic blocks, starting with FIRST_BB
6016e4b17023SJohn Marino and following a trace through the CFG.
6017e4b17023SJohn Marino
6018e4b17023SJohn Marino If all paths starting at FIRST_BB have been followed, or no new path
6019e4b17023SJohn Marino starting at FIRST_BB can be constructed, this function returns FALSE.
6020e4b17023SJohn Marino Otherwise, DATA->path is filled and the function returns TRUE indicating
6021e4b17023SJohn Marino that a path to follow was found.
6022e4b17023SJohn Marino
6023e4b17023SJohn Marino If FOLLOW_JUMPS is false, the maximum path length is 1 and the only
6024e4b17023SJohn Marino block in the path will be FIRST_BB. */
6025e4b17023SJohn Marino
6026e4b17023SJohn Marino static bool
cse_find_path(basic_block first_bb,struct cse_basic_block_data * data,int follow_jumps)6027e4b17023SJohn Marino cse_find_path (basic_block first_bb, struct cse_basic_block_data *data,
6028e4b17023SJohn Marino int follow_jumps)
6029e4b17023SJohn Marino {
6030e4b17023SJohn Marino basic_block bb;
6031e4b17023SJohn Marino edge e;
6032e4b17023SJohn Marino int path_size;
6033e4b17023SJohn Marino
6034e4b17023SJohn Marino SET_BIT (cse_visited_basic_blocks, first_bb->index);
6035e4b17023SJohn Marino
6036e4b17023SJohn Marino /* See if there is a previous path. */
6037e4b17023SJohn Marino path_size = data->path_size;
6038e4b17023SJohn Marino
6039e4b17023SJohn Marino /* There is a previous path. Make sure it started with FIRST_BB. */
6040e4b17023SJohn Marino if (path_size)
6041e4b17023SJohn Marino gcc_assert (data->path[0].bb == first_bb);
6042e4b17023SJohn Marino
6043e4b17023SJohn Marino /* There was only one basic block in the last path. Clear the path and
6044e4b17023SJohn Marino return, so that paths starting at another basic block can be tried. */
6045e4b17023SJohn Marino if (path_size == 1)
6046e4b17023SJohn Marino {
6047e4b17023SJohn Marino path_size = 0;
6048e4b17023SJohn Marino goto done;
6049e4b17023SJohn Marino }
6050e4b17023SJohn Marino
6051e4b17023SJohn Marino /* If the path was empty from the beginning, construct a new path. */
6052e4b17023SJohn Marino if (path_size == 0)
6053e4b17023SJohn Marino data->path[path_size++].bb = first_bb;
6054e4b17023SJohn Marino else
6055e4b17023SJohn Marino {
6056e4b17023SJohn Marino /* Otherwise, path_size must be equal to or greater than 2, because
6057e4b17023SJohn Marino a previous path exists that is at least two basic blocks long.
6058e4b17023SJohn Marino
6059e4b17023SJohn Marino Update the previous branch path, if any. If the last branch was
6060e4b17023SJohn Marino previously along the branch edge, take the fallthrough edge now. */
6061e4b17023SJohn Marino while (path_size >= 2)
6062e4b17023SJohn Marino {
6063e4b17023SJohn Marino basic_block last_bb_in_path, previous_bb_in_path;
6064e4b17023SJohn Marino edge e;
6065e4b17023SJohn Marino
6066e4b17023SJohn Marino --path_size;
6067e4b17023SJohn Marino last_bb_in_path = data->path[path_size].bb;
6068e4b17023SJohn Marino previous_bb_in_path = data->path[path_size - 1].bb;
6069e4b17023SJohn Marino
6070e4b17023SJohn Marino /* If we previously followed a path along the branch edge, try
6071e4b17023SJohn Marino the fallthru edge now. */
6072e4b17023SJohn Marino if (EDGE_COUNT (previous_bb_in_path->succs) == 2
6073e4b17023SJohn Marino && any_condjump_p (BB_END (previous_bb_in_path))
6074e4b17023SJohn Marino && (e = find_edge (previous_bb_in_path, last_bb_in_path))
6075e4b17023SJohn Marino && e == BRANCH_EDGE (previous_bb_in_path))
6076e4b17023SJohn Marino {
6077e4b17023SJohn Marino bb = FALLTHRU_EDGE (previous_bb_in_path)->dest;
6078e4b17023SJohn Marino if (bb != EXIT_BLOCK_PTR
6079e4b17023SJohn Marino && single_pred_p (bb)
6080e4b17023SJohn Marino /* We used to assert here that we would only see blocks
6081e4b17023SJohn Marino that we have not visited yet. But we may end up
6082e4b17023SJohn Marino visiting basic blocks twice if the CFG has changed
6083e4b17023SJohn Marino in this run of cse_main, because when the CFG changes
6084e4b17023SJohn Marino the topological sort of the CFG also changes. A basic
6085e4b17023SJohn Marino blocks that previously had more than two predecessors
6086e4b17023SJohn Marino may now have a single predecessor, and become part of
6087e4b17023SJohn Marino a path that starts at another basic block.
6088e4b17023SJohn Marino
6089e4b17023SJohn Marino We still want to visit each basic block only once, so
6090e4b17023SJohn Marino halt the path here if we have already visited BB. */
6091e4b17023SJohn Marino && !TEST_BIT (cse_visited_basic_blocks, bb->index))
6092e4b17023SJohn Marino {
6093e4b17023SJohn Marino SET_BIT (cse_visited_basic_blocks, bb->index);
6094e4b17023SJohn Marino data->path[path_size++].bb = bb;
6095e4b17023SJohn Marino break;
6096e4b17023SJohn Marino }
6097e4b17023SJohn Marino }
6098e4b17023SJohn Marino
6099e4b17023SJohn Marino data->path[path_size].bb = NULL;
6100e4b17023SJohn Marino }
6101e4b17023SJohn Marino
6102e4b17023SJohn Marino /* If only one block remains in the path, bail. */
6103e4b17023SJohn Marino if (path_size == 1)
6104e4b17023SJohn Marino {
6105e4b17023SJohn Marino path_size = 0;
6106e4b17023SJohn Marino goto done;
6107e4b17023SJohn Marino }
6108e4b17023SJohn Marino }
6109e4b17023SJohn Marino
6110e4b17023SJohn Marino /* Extend the path if possible. */
6111e4b17023SJohn Marino if (follow_jumps)
6112e4b17023SJohn Marino {
6113e4b17023SJohn Marino bb = data->path[path_size - 1].bb;
6114e4b17023SJohn Marino while (bb && path_size < PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH))
6115e4b17023SJohn Marino {
6116e4b17023SJohn Marino if (single_succ_p (bb))
6117e4b17023SJohn Marino e = single_succ_edge (bb);
6118e4b17023SJohn Marino else if (EDGE_COUNT (bb->succs) == 2
6119e4b17023SJohn Marino && any_condjump_p (BB_END (bb)))
6120e4b17023SJohn Marino {
6121e4b17023SJohn Marino /* First try to follow the branch. If that doesn't lead
6122e4b17023SJohn Marino to a useful path, follow the fallthru edge. */
6123e4b17023SJohn Marino e = BRANCH_EDGE (bb);
6124e4b17023SJohn Marino if (!single_pred_p (e->dest))
6125e4b17023SJohn Marino e = FALLTHRU_EDGE (bb);
6126e4b17023SJohn Marino }
6127e4b17023SJohn Marino else
6128e4b17023SJohn Marino e = NULL;
6129e4b17023SJohn Marino
6130e4b17023SJohn Marino if (e
6131e4b17023SJohn Marino && !((e->flags & EDGE_ABNORMAL_CALL) && cfun->has_nonlocal_label)
6132e4b17023SJohn Marino && e->dest != EXIT_BLOCK_PTR
6133e4b17023SJohn Marino && single_pred_p (e->dest)
6134e4b17023SJohn Marino /* Avoid visiting basic blocks twice. The large comment
6135e4b17023SJohn Marino above explains why this can happen. */
6136e4b17023SJohn Marino && !TEST_BIT (cse_visited_basic_blocks, e->dest->index))
6137e4b17023SJohn Marino {
6138e4b17023SJohn Marino basic_block bb2 = e->dest;
6139e4b17023SJohn Marino SET_BIT (cse_visited_basic_blocks, bb2->index);
6140e4b17023SJohn Marino data->path[path_size++].bb = bb2;
6141e4b17023SJohn Marino bb = bb2;
6142e4b17023SJohn Marino }
6143e4b17023SJohn Marino else
6144e4b17023SJohn Marino bb = NULL;
6145e4b17023SJohn Marino }
6146e4b17023SJohn Marino }
6147e4b17023SJohn Marino
6148e4b17023SJohn Marino done:
6149e4b17023SJohn Marino data->path_size = path_size;
6150e4b17023SJohn Marino return path_size != 0;
6151e4b17023SJohn Marino }
6152e4b17023SJohn Marino
6153e4b17023SJohn Marino /* Dump the path in DATA to file F. NSETS is the number of sets
6154e4b17023SJohn Marino in the path. */
6155e4b17023SJohn Marino
6156e4b17023SJohn Marino static void
cse_dump_path(struct cse_basic_block_data * data,int nsets,FILE * f)6157e4b17023SJohn Marino cse_dump_path (struct cse_basic_block_data *data, int nsets, FILE *f)
6158e4b17023SJohn Marino {
6159e4b17023SJohn Marino int path_entry;
6160e4b17023SJohn Marino
6161e4b17023SJohn Marino fprintf (f, ";; Following path with %d sets: ", nsets);
6162e4b17023SJohn Marino for (path_entry = 0; path_entry < data->path_size; path_entry++)
6163e4b17023SJohn Marino fprintf (f, "%d ", (data->path[path_entry].bb)->index);
6164e4b17023SJohn Marino fputc ('\n', dump_file);
6165e4b17023SJohn Marino fflush (f);
6166e4b17023SJohn Marino }
6167e4b17023SJohn Marino
6168e4b17023SJohn Marino
6169e4b17023SJohn Marino /* Return true if BB has exception handling successor edges. */
6170e4b17023SJohn Marino
6171e4b17023SJohn Marino static bool
have_eh_succ_edges(basic_block bb)6172e4b17023SJohn Marino have_eh_succ_edges (basic_block bb)
6173e4b17023SJohn Marino {
6174e4b17023SJohn Marino edge e;
6175e4b17023SJohn Marino edge_iterator ei;
6176e4b17023SJohn Marino
6177e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
6178e4b17023SJohn Marino if (e->flags & EDGE_EH)
6179e4b17023SJohn Marino return true;
6180e4b17023SJohn Marino
6181e4b17023SJohn Marino return false;
6182e4b17023SJohn Marino }
6183e4b17023SJohn Marino
6184e4b17023SJohn Marino
6185e4b17023SJohn Marino /* Scan to the end of the path described by DATA. Return an estimate of
6186e4b17023SJohn Marino the total number of SETs of all insns in the path. */
6187e4b17023SJohn Marino
6188e4b17023SJohn Marino static void
cse_prescan_path(struct cse_basic_block_data * data)6189e4b17023SJohn Marino cse_prescan_path (struct cse_basic_block_data *data)
6190e4b17023SJohn Marino {
6191e4b17023SJohn Marino int nsets = 0;
6192e4b17023SJohn Marino int path_size = data->path_size;
6193e4b17023SJohn Marino int path_entry;
6194e4b17023SJohn Marino
6195e4b17023SJohn Marino /* Scan to end of each basic block in the path. */
6196e4b17023SJohn Marino for (path_entry = 0; path_entry < path_size; path_entry++)
6197e4b17023SJohn Marino {
6198e4b17023SJohn Marino basic_block bb;
6199e4b17023SJohn Marino rtx insn;
6200e4b17023SJohn Marino
6201e4b17023SJohn Marino bb = data->path[path_entry].bb;
6202e4b17023SJohn Marino
6203e4b17023SJohn Marino FOR_BB_INSNS (bb, insn)
6204e4b17023SJohn Marino {
6205e4b17023SJohn Marino if (!INSN_P (insn))
6206e4b17023SJohn Marino continue;
6207e4b17023SJohn Marino
6208e4b17023SJohn Marino /* A PARALLEL can have lots of SETs in it,
6209e4b17023SJohn Marino especially if it is really an ASM_OPERANDS. */
6210e4b17023SJohn Marino if (GET_CODE (PATTERN (insn)) == PARALLEL)
6211e4b17023SJohn Marino nsets += XVECLEN (PATTERN (insn), 0);
6212e4b17023SJohn Marino else
6213e4b17023SJohn Marino nsets += 1;
6214e4b17023SJohn Marino }
6215e4b17023SJohn Marino }
6216e4b17023SJohn Marino
6217e4b17023SJohn Marino data->nsets = nsets;
6218e4b17023SJohn Marino }
6219e4b17023SJohn Marino
6220e4b17023SJohn Marino /* Process a single extended basic block described by EBB_DATA. */
6221e4b17023SJohn Marino
6222e4b17023SJohn Marino static void
cse_extended_basic_block(struct cse_basic_block_data * ebb_data)6223e4b17023SJohn Marino cse_extended_basic_block (struct cse_basic_block_data *ebb_data)
6224e4b17023SJohn Marino {
6225e4b17023SJohn Marino int path_size = ebb_data->path_size;
6226e4b17023SJohn Marino int path_entry;
6227e4b17023SJohn Marino int num_insns = 0;
6228e4b17023SJohn Marino
6229e4b17023SJohn Marino /* Allocate the space needed by qty_table. */
6230e4b17023SJohn Marino qty_table = XNEWVEC (struct qty_table_elem, max_qty);
6231e4b17023SJohn Marino
6232e4b17023SJohn Marino new_basic_block ();
6233e4b17023SJohn Marino cse_ebb_live_in = df_get_live_in (ebb_data->path[0].bb);
6234e4b17023SJohn Marino cse_ebb_live_out = df_get_live_out (ebb_data->path[path_size - 1].bb);
6235e4b17023SJohn Marino for (path_entry = 0; path_entry < path_size; path_entry++)
6236e4b17023SJohn Marino {
6237e4b17023SJohn Marino basic_block bb;
6238e4b17023SJohn Marino rtx insn;
6239e4b17023SJohn Marino
6240e4b17023SJohn Marino bb = ebb_data->path[path_entry].bb;
6241e4b17023SJohn Marino
6242e4b17023SJohn Marino /* Invalidate recorded information for eh regs if there is an EH
6243e4b17023SJohn Marino edge pointing to that bb. */
6244e4b17023SJohn Marino if (bb_has_eh_pred (bb))
6245e4b17023SJohn Marino {
6246e4b17023SJohn Marino df_ref *def_rec;
6247e4b17023SJohn Marino
6248e4b17023SJohn Marino for (def_rec = df_get_artificial_defs (bb->index); *def_rec; def_rec++)
6249e4b17023SJohn Marino {
6250e4b17023SJohn Marino df_ref def = *def_rec;
6251e4b17023SJohn Marino if (DF_REF_FLAGS (def) & DF_REF_AT_TOP)
6252e4b17023SJohn Marino invalidate (DF_REF_REG (def), GET_MODE (DF_REF_REG (def)));
6253e4b17023SJohn Marino }
6254e4b17023SJohn Marino }
6255e4b17023SJohn Marino
6256e4b17023SJohn Marino optimize_this_for_speed_p = optimize_bb_for_speed_p (bb);
6257e4b17023SJohn Marino FOR_BB_INSNS (bb, insn)
6258e4b17023SJohn Marino {
6259e4b17023SJohn Marino /* If we have processed 1,000 insns, flush the hash table to
6260e4b17023SJohn Marino avoid extreme quadratic behavior. We must not include NOTEs
6261e4b17023SJohn Marino in the count since there may be more of them when generating
6262e4b17023SJohn Marino debugging information. If we clear the table at different
6263e4b17023SJohn Marino times, code generated with -g -O might be different than code
6264e4b17023SJohn Marino generated with -O but not -g.
6265e4b17023SJohn Marino
6266e4b17023SJohn Marino FIXME: This is a real kludge and needs to be done some other
6267e4b17023SJohn Marino way. */
6268e4b17023SJohn Marino if (NONDEBUG_INSN_P (insn)
6269e4b17023SJohn Marino && num_insns++ > PARAM_VALUE (PARAM_MAX_CSE_INSNS))
6270e4b17023SJohn Marino {
6271e4b17023SJohn Marino flush_hash_table ();
6272e4b17023SJohn Marino num_insns = 0;
6273e4b17023SJohn Marino }
6274e4b17023SJohn Marino
6275e4b17023SJohn Marino if (INSN_P (insn))
6276e4b17023SJohn Marino {
6277e4b17023SJohn Marino /* Process notes first so we have all notes in canonical forms
6278e4b17023SJohn Marino when looking for duplicate operations. */
6279e4b17023SJohn Marino if (REG_NOTES (insn))
6280e4b17023SJohn Marino {
6281e4b17023SJohn Marino bool changed = false;
6282e4b17023SJohn Marino REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn),
6283e4b17023SJohn Marino NULL_RTX, &changed);
6284e4b17023SJohn Marino if (changed)
6285e4b17023SJohn Marino df_notes_rescan (insn);
6286e4b17023SJohn Marino }
6287e4b17023SJohn Marino
6288e4b17023SJohn Marino cse_insn (insn);
6289e4b17023SJohn Marino
6290e4b17023SJohn Marino /* If we haven't already found an insn where we added a LABEL_REF,
6291e4b17023SJohn Marino check this one. */
6292e4b17023SJohn Marino if (INSN_P (insn) && !recorded_label_ref
6293e4b17023SJohn Marino && for_each_rtx (&PATTERN (insn), check_for_label_ref,
6294e4b17023SJohn Marino (void *) insn))
6295e4b17023SJohn Marino recorded_label_ref = true;
6296e4b17023SJohn Marino
6297e4b17023SJohn Marino #ifdef HAVE_cc0
6298e4b17023SJohn Marino if (NONDEBUG_INSN_P (insn))
6299e4b17023SJohn Marino {
6300e4b17023SJohn Marino /* If the previous insn sets CC0 and this insn no
6301e4b17023SJohn Marino longer references CC0, delete the previous insn.
6302e4b17023SJohn Marino Here we use fact that nothing expects CC0 to be
6303e4b17023SJohn Marino valid over an insn, which is true until the final
6304e4b17023SJohn Marino pass. */
6305e4b17023SJohn Marino rtx prev_insn, tem;
6306e4b17023SJohn Marino
6307e4b17023SJohn Marino prev_insn = prev_nonnote_nondebug_insn (insn);
6308e4b17023SJohn Marino if (prev_insn && NONJUMP_INSN_P (prev_insn)
6309e4b17023SJohn Marino && (tem = single_set (prev_insn)) != NULL_RTX
6310e4b17023SJohn Marino && SET_DEST (tem) == cc0_rtx
6311e4b17023SJohn Marino && ! reg_mentioned_p (cc0_rtx, PATTERN (insn)))
6312e4b17023SJohn Marino delete_insn (prev_insn);
6313e4b17023SJohn Marino
6314e4b17023SJohn Marino /* If this insn is not the last insn in the basic
6315e4b17023SJohn Marino block, it will be PREV_INSN(insn) in the next
6316e4b17023SJohn Marino iteration. If we recorded any CC0-related
6317e4b17023SJohn Marino information for this insn, remember it. */
6318e4b17023SJohn Marino if (insn != BB_END (bb))
6319e4b17023SJohn Marino {
6320e4b17023SJohn Marino prev_insn_cc0 = this_insn_cc0;
6321e4b17023SJohn Marino prev_insn_cc0_mode = this_insn_cc0_mode;
6322e4b17023SJohn Marino }
6323e4b17023SJohn Marino }
6324e4b17023SJohn Marino #endif
6325e4b17023SJohn Marino }
6326e4b17023SJohn Marino }
6327e4b17023SJohn Marino
6328e4b17023SJohn Marino /* With non-call exceptions, we are not always able to update
6329e4b17023SJohn Marino the CFG properly inside cse_insn. So clean up possibly
6330e4b17023SJohn Marino redundant EH edges here. */
6331e4b17023SJohn Marino if (cfun->can_throw_non_call_exceptions && have_eh_succ_edges (bb))
6332e4b17023SJohn Marino cse_cfg_altered |= purge_dead_edges (bb);
6333e4b17023SJohn Marino
6334e4b17023SJohn Marino /* If we changed a conditional jump, we may have terminated
6335e4b17023SJohn Marino the path we are following. Check that by verifying that
6336e4b17023SJohn Marino the edge we would take still exists. If the edge does
6337e4b17023SJohn Marino not exist anymore, purge the remainder of the path.
6338e4b17023SJohn Marino Note that this will cause us to return to the caller. */
6339e4b17023SJohn Marino if (path_entry < path_size - 1)
6340e4b17023SJohn Marino {
6341e4b17023SJohn Marino basic_block next_bb = ebb_data->path[path_entry + 1].bb;
6342e4b17023SJohn Marino if (!find_edge (bb, next_bb))
6343e4b17023SJohn Marino {
6344e4b17023SJohn Marino do
6345e4b17023SJohn Marino {
6346e4b17023SJohn Marino path_size--;
6347e4b17023SJohn Marino
6348e4b17023SJohn Marino /* If we truncate the path, we must also reset the
6349e4b17023SJohn Marino visited bit on the remaining blocks in the path,
6350e4b17023SJohn Marino or we will never visit them at all. */
6351e4b17023SJohn Marino RESET_BIT (cse_visited_basic_blocks,
6352e4b17023SJohn Marino ebb_data->path[path_size].bb->index);
6353e4b17023SJohn Marino ebb_data->path[path_size].bb = NULL;
6354e4b17023SJohn Marino }
6355e4b17023SJohn Marino while (path_size - 1 != path_entry);
6356e4b17023SJohn Marino ebb_data->path_size = path_size;
6357e4b17023SJohn Marino }
6358e4b17023SJohn Marino }
6359e4b17023SJohn Marino
6360e4b17023SJohn Marino /* If this is a conditional jump insn, record any known
6361e4b17023SJohn Marino equivalences due to the condition being tested. */
6362e4b17023SJohn Marino insn = BB_END (bb);
6363e4b17023SJohn Marino if (path_entry < path_size - 1
6364e4b17023SJohn Marino && JUMP_P (insn)
6365e4b17023SJohn Marino && single_set (insn)
6366e4b17023SJohn Marino && any_condjump_p (insn))
6367e4b17023SJohn Marino {
6368e4b17023SJohn Marino basic_block next_bb = ebb_data->path[path_entry + 1].bb;
6369e4b17023SJohn Marino bool taken = (next_bb == BRANCH_EDGE (bb)->dest);
6370e4b17023SJohn Marino record_jump_equiv (insn, taken);
6371e4b17023SJohn Marino }
6372e4b17023SJohn Marino
6373e4b17023SJohn Marino #ifdef HAVE_cc0
6374e4b17023SJohn Marino /* Clear the CC0-tracking related insns, they can't provide
6375e4b17023SJohn Marino useful information across basic block boundaries. */
6376e4b17023SJohn Marino prev_insn_cc0 = 0;
6377e4b17023SJohn Marino #endif
6378e4b17023SJohn Marino }
6379e4b17023SJohn Marino
6380e4b17023SJohn Marino gcc_assert (next_qty <= max_qty);
6381e4b17023SJohn Marino
6382e4b17023SJohn Marino free (qty_table);
6383e4b17023SJohn Marino }
6384e4b17023SJohn Marino
6385e4b17023SJohn Marino
6386e4b17023SJohn Marino /* Perform cse on the instructions of a function.
6387e4b17023SJohn Marino F is the first instruction.
6388e4b17023SJohn Marino NREGS is one plus the highest pseudo-reg number used in the instruction.
6389e4b17023SJohn Marino
6390e4b17023SJohn Marino Return 2 if jump optimizations should be redone due to simplifications
6391e4b17023SJohn Marino in conditional jump instructions.
6392e4b17023SJohn Marino Return 1 if the CFG should be cleaned up because it has been modified.
6393e4b17023SJohn Marino Return 0 otherwise. */
6394e4b17023SJohn Marino
6395e4b17023SJohn Marino int
cse_main(rtx f ATTRIBUTE_UNUSED,int nregs)6396e4b17023SJohn Marino cse_main (rtx f ATTRIBUTE_UNUSED, int nregs)
6397e4b17023SJohn Marino {
6398e4b17023SJohn Marino struct cse_basic_block_data ebb_data;
6399e4b17023SJohn Marino basic_block bb;
6400e4b17023SJohn Marino int *rc_order = XNEWVEC (int, last_basic_block);
6401e4b17023SJohn Marino int i, n_blocks;
6402e4b17023SJohn Marino
6403e4b17023SJohn Marino df_set_flags (DF_LR_RUN_DCE);
6404e4b17023SJohn Marino df_analyze ();
6405e4b17023SJohn Marino df_set_flags (DF_DEFER_INSN_RESCAN);
6406e4b17023SJohn Marino
6407e4b17023SJohn Marino reg_scan (get_insns (), max_reg_num ());
6408e4b17023SJohn Marino init_cse_reg_info (nregs);
6409e4b17023SJohn Marino
6410e4b17023SJohn Marino ebb_data.path = XNEWVEC (struct branch_path,
6411e4b17023SJohn Marino PARAM_VALUE (PARAM_MAX_CSE_PATH_LENGTH));
6412e4b17023SJohn Marino
6413e4b17023SJohn Marino cse_cfg_altered = false;
6414e4b17023SJohn Marino cse_jumps_altered = false;
6415e4b17023SJohn Marino recorded_label_ref = false;
6416e4b17023SJohn Marino constant_pool_entries_cost = 0;
6417e4b17023SJohn Marino constant_pool_entries_regcost = 0;
6418e4b17023SJohn Marino ebb_data.path_size = 0;
6419e4b17023SJohn Marino ebb_data.nsets = 0;
6420e4b17023SJohn Marino rtl_hooks = cse_rtl_hooks;
6421e4b17023SJohn Marino
6422e4b17023SJohn Marino init_recog ();
6423e4b17023SJohn Marino init_alias_analysis ();
6424e4b17023SJohn Marino
6425e4b17023SJohn Marino reg_eqv_table = XNEWVEC (struct reg_eqv_elem, nregs);
6426e4b17023SJohn Marino
6427e4b17023SJohn Marino /* Set up the table of already visited basic blocks. */
6428e4b17023SJohn Marino cse_visited_basic_blocks = sbitmap_alloc (last_basic_block);
6429e4b17023SJohn Marino sbitmap_zero (cse_visited_basic_blocks);
6430e4b17023SJohn Marino
6431e4b17023SJohn Marino /* Loop over basic blocks in reverse completion order (RPO),
6432e4b17023SJohn Marino excluding the ENTRY and EXIT blocks. */
6433e4b17023SJohn Marino n_blocks = pre_and_rev_post_order_compute (NULL, rc_order, false);
6434e4b17023SJohn Marino i = 0;
6435e4b17023SJohn Marino while (i < n_blocks)
6436e4b17023SJohn Marino {
6437e4b17023SJohn Marino /* Find the first block in the RPO queue that we have not yet
6438e4b17023SJohn Marino processed before. */
6439e4b17023SJohn Marino do
6440e4b17023SJohn Marino {
6441e4b17023SJohn Marino bb = BASIC_BLOCK (rc_order[i++]);
6442e4b17023SJohn Marino }
6443e4b17023SJohn Marino while (TEST_BIT (cse_visited_basic_blocks, bb->index)
6444e4b17023SJohn Marino && i < n_blocks);
6445e4b17023SJohn Marino
6446e4b17023SJohn Marino /* Find all paths starting with BB, and process them. */
6447e4b17023SJohn Marino while (cse_find_path (bb, &ebb_data, flag_cse_follow_jumps))
6448e4b17023SJohn Marino {
6449e4b17023SJohn Marino /* Pre-scan the path. */
6450e4b17023SJohn Marino cse_prescan_path (&ebb_data);
6451e4b17023SJohn Marino
6452e4b17023SJohn Marino /* If this basic block has no sets, skip it. */
6453e4b17023SJohn Marino if (ebb_data.nsets == 0)
6454e4b17023SJohn Marino continue;
6455e4b17023SJohn Marino
6456e4b17023SJohn Marino /* Get a reasonable estimate for the maximum number of qty's
6457e4b17023SJohn Marino needed for this path. For this, we take the number of sets
6458e4b17023SJohn Marino and multiply that by MAX_RECOG_OPERANDS. */
6459e4b17023SJohn Marino max_qty = ebb_data.nsets * MAX_RECOG_OPERANDS;
6460e4b17023SJohn Marino
6461e4b17023SJohn Marino /* Dump the path we're about to process. */
6462e4b17023SJohn Marino if (dump_file)
6463e4b17023SJohn Marino cse_dump_path (&ebb_data, ebb_data.nsets, dump_file);
6464e4b17023SJohn Marino
6465e4b17023SJohn Marino cse_extended_basic_block (&ebb_data);
6466e4b17023SJohn Marino }
6467e4b17023SJohn Marino }
6468e4b17023SJohn Marino
6469e4b17023SJohn Marino /* Clean up. */
6470e4b17023SJohn Marino end_alias_analysis ();
6471e4b17023SJohn Marino free (reg_eqv_table);
6472e4b17023SJohn Marino free (ebb_data.path);
6473e4b17023SJohn Marino sbitmap_free (cse_visited_basic_blocks);
6474e4b17023SJohn Marino free (rc_order);
6475e4b17023SJohn Marino rtl_hooks = general_rtl_hooks;
6476e4b17023SJohn Marino
6477e4b17023SJohn Marino if (cse_jumps_altered || recorded_label_ref)
6478e4b17023SJohn Marino return 2;
6479e4b17023SJohn Marino else if (cse_cfg_altered)
6480e4b17023SJohn Marino return 1;
6481e4b17023SJohn Marino else
6482e4b17023SJohn Marino return 0;
6483e4b17023SJohn Marino }
6484e4b17023SJohn Marino
6485e4b17023SJohn Marino /* Called via for_each_rtx to see if an insn is using a LABEL_REF for
6486e4b17023SJohn Marino which there isn't a REG_LABEL_OPERAND note.
6487e4b17023SJohn Marino Return one if so. DATA is the insn. */
6488e4b17023SJohn Marino
6489e4b17023SJohn Marino static int
check_for_label_ref(rtx * rtl,void * data)6490e4b17023SJohn Marino check_for_label_ref (rtx *rtl, void *data)
6491e4b17023SJohn Marino {
6492e4b17023SJohn Marino rtx insn = (rtx) data;
6493e4b17023SJohn Marino
6494e4b17023SJohn Marino /* If this insn uses a LABEL_REF and there isn't a REG_LABEL_OPERAND
6495e4b17023SJohn Marino note for it, we must rerun jump since it needs to place the note. If
6496e4b17023SJohn Marino this is a LABEL_REF for a CODE_LABEL that isn't in the insn chain,
6497e4b17023SJohn Marino don't do this since no REG_LABEL_OPERAND will be added. */
6498e4b17023SJohn Marino return (GET_CODE (*rtl) == LABEL_REF
6499e4b17023SJohn Marino && ! LABEL_REF_NONLOCAL_P (*rtl)
6500e4b17023SJohn Marino && (!JUMP_P (insn)
6501e4b17023SJohn Marino || !label_is_jump_target_p (XEXP (*rtl, 0), insn))
6502e4b17023SJohn Marino && LABEL_P (XEXP (*rtl, 0))
6503e4b17023SJohn Marino && INSN_UID (XEXP (*rtl, 0)) != 0
6504e4b17023SJohn Marino && ! find_reg_note (insn, REG_LABEL_OPERAND, XEXP (*rtl, 0)));
6505e4b17023SJohn Marino }
6506e4b17023SJohn Marino
6507e4b17023SJohn Marino /* Count the number of times registers are used (not set) in X.
6508e4b17023SJohn Marino COUNTS is an array in which we accumulate the count, INCR is how much
6509e4b17023SJohn Marino we count each register usage.
6510e4b17023SJohn Marino
6511e4b17023SJohn Marino Don't count a usage of DEST, which is the SET_DEST of a SET which
6512e4b17023SJohn Marino contains X in its SET_SRC. This is because such a SET does not
6513e4b17023SJohn Marino modify the liveness of DEST.
6514e4b17023SJohn Marino DEST is set to pc_rtx for a trapping insn, or for an insn with side effects.
6515e4b17023SJohn Marino We must then count uses of a SET_DEST regardless, because the insn can't be
6516e4b17023SJohn Marino deleted here. */
6517e4b17023SJohn Marino
6518e4b17023SJohn Marino static void
count_reg_usage(rtx x,int * counts,rtx dest,int incr)6519e4b17023SJohn Marino count_reg_usage (rtx x, int *counts, rtx dest, int incr)
6520e4b17023SJohn Marino {
6521e4b17023SJohn Marino enum rtx_code code;
6522e4b17023SJohn Marino rtx note;
6523e4b17023SJohn Marino const char *fmt;
6524e4b17023SJohn Marino int i, j;
6525e4b17023SJohn Marino
6526e4b17023SJohn Marino if (x == 0)
6527e4b17023SJohn Marino return;
6528e4b17023SJohn Marino
6529e4b17023SJohn Marino switch (code = GET_CODE (x))
6530e4b17023SJohn Marino {
6531e4b17023SJohn Marino case REG:
6532e4b17023SJohn Marino if (x != dest)
6533e4b17023SJohn Marino counts[REGNO (x)] += incr;
6534e4b17023SJohn Marino return;
6535e4b17023SJohn Marino
6536e4b17023SJohn Marino case PC:
6537e4b17023SJohn Marino case CC0:
6538e4b17023SJohn Marino case CONST:
6539e4b17023SJohn Marino case CONST_INT:
6540e4b17023SJohn Marino case CONST_DOUBLE:
6541e4b17023SJohn Marino case CONST_FIXED:
6542e4b17023SJohn Marino case CONST_VECTOR:
6543e4b17023SJohn Marino case SYMBOL_REF:
6544e4b17023SJohn Marino case LABEL_REF:
6545e4b17023SJohn Marino return;
6546e4b17023SJohn Marino
6547e4b17023SJohn Marino case CLOBBER:
6548e4b17023SJohn Marino /* If we are clobbering a MEM, mark any registers inside the address
6549e4b17023SJohn Marino as being used. */
6550e4b17023SJohn Marino if (MEM_P (XEXP (x, 0)))
6551e4b17023SJohn Marino count_reg_usage (XEXP (XEXP (x, 0), 0), counts, NULL_RTX, incr);
6552e4b17023SJohn Marino return;
6553e4b17023SJohn Marino
6554e4b17023SJohn Marino case SET:
6555e4b17023SJohn Marino /* Unless we are setting a REG, count everything in SET_DEST. */
6556e4b17023SJohn Marino if (!REG_P (SET_DEST (x)))
6557e4b17023SJohn Marino count_reg_usage (SET_DEST (x), counts, NULL_RTX, incr);
6558e4b17023SJohn Marino count_reg_usage (SET_SRC (x), counts,
6559e4b17023SJohn Marino dest ? dest : SET_DEST (x),
6560e4b17023SJohn Marino incr);
6561e4b17023SJohn Marino return;
6562e4b17023SJohn Marino
6563e4b17023SJohn Marino case DEBUG_INSN:
6564e4b17023SJohn Marino return;
6565e4b17023SJohn Marino
6566e4b17023SJohn Marino case CALL_INSN:
6567e4b17023SJohn Marino case INSN:
6568e4b17023SJohn Marino case JUMP_INSN:
6569e4b17023SJohn Marino /* We expect dest to be NULL_RTX here. If the insn may trap,
6570e4b17023SJohn Marino or if it cannot be deleted due to side-effects, mark this fact
6571e4b17023SJohn Marino by setting DEST to pc_rtx. */
6572e4b17023SJohn Marino if (insn_could_throw_p (x) || side_effects_p (PATTERN (x)))
6573e4b17023SJohn Marino dest = pc_rtx;
6574e4b17023SJohn Marino if (code == CALL_INSN)
6575e4b17023SJohn Marino count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, dest, incr);
6576e4b17023SJohn Marino count_reg_usage (PATTERN (x), counts, dest, incr);
6577e4b17023SJohn Marino
6578e4b17023SJohn Marino /* Things used in a REG_EQUAL note aren't dead since loop may try to
6579e4b17023SJohn Marino use them. */
6580e4b17023SJohn Marino
6581e4b17023SJohn Marino note = find_reg_equal_equiv_note (x);
6582e4b17023SJohn Marino if (note)
6583e4b17023SJohn Marino {
6584e4b17023SJohn Marino rtx eqv = XEXP (note, 0);
6585e4b17023SJohn Marino
6586e4b17023SJohn Marino if (GET_CODE (eqv) == EXPR_LIST)
6587e4b17023SJohn Marino /* This REG_EQUAL note describes the result of a function call.
6588e4b17023SJohn Marino Process all the arguments. */
6589e4b17023SJohn Marino do
6590e4b17023SJohn Marino {
6591e4b17023SJohn Marino count_reg_usage (XEXP (eqv, 0), counts, dest, incr);
6592e4b17023SJohn Marino eqv = XEXP (eqv, 1);
6593e4b17023SJohn Marino }
6594e4b17023SJohn Marino while (eqv && GET_CODE (eqv) == EXPR_LIST);
6595e4b17023SJohn Marino else
6596e4b17023SJohn Marino count_reg_usage (eqv, counts, dest, incr);
6597e4b17023SJohn Marino }
6598e4b17023SJohn Marino return;
6599e4b17023SJohn Marino
6600e4b17023SJohn Marino case EXPR_LIST:
6601e4b17023SJohn Marino if (REG_NOTE_KIND (x) == REG_EQUAL
6602e4b17023SJohn Marino || (REG_NOTE_KIND (x) != REG_NONNEG && GET_CODE (XEXP (x,0)) == USE)
6603e4b17023SJohn Marino /* FUNCTION_USAGE expression lists may include (CLOBBER (mem /u)),
6604e4b17023SJohn Marino involving registers in the address. */
6605e4b17023SJohn Marino || GET_CODE (XEXP (x, 0)) == CLOBBER)
6606e4b17023SJohn Marino count_reg_usage (XEXP (x, 0), counts, NULL_RTX, incr);
6607e4b17023SJohn Marino
6608e4b17023SJohn Marino count_reg_usage (XEXP (x, 1), counts, NULL_RTX, incr);
6609e4b17023SJohn Marino return;
6610e4b17023SJohn Marino
6611e4b17023SJohn Marino case ASM_OPERANDS:
6612e4b17023SJohn Marino /* Iterate over just the inputs, not the constraints as well. */
6613e4b17023SJohn Marino for (i = ASM_OPERANDS_INPUT_LENGTH (x) - 1; i >= 0; i--)
6614e4b17023SJohn Marino count_reg_usage (ASM_OPERANDS_INPUT (x, i), counts, dest, incr);
6615e4b17023SJohn Marino return;
6616e4b17023SJohn Marino
6617e4b17023SJohn Marino case INSN_LIST:
6618e4b17023SJohn Marino gcc_unreachable ();
6619e4b17023SJohn Marino
6620e4b17023SJohn Marino default:
6621e4b17023SJohn Marino break;
6622e4b17023SJohn Marino }
6623e4b17023SJohn Marino
6624e4b17023SJohn Marino fmt = GET_RTX_FORMAT (code);
6625e4b17023SJohn Marino for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
6626e4b17023SJohn Marino {
6627e4b17023SJohn Marino if (fmt[i] == 'e')
6628e4b17023SJohn Marino count_reg_usage (XEXP (x, i), counts, dest, incr);
6629e4b17023SJohn Marino else if (fmt[i] == 'E')
6630e4b17023SJohn Marino for (j = XVECLEN (x, i) - 1; j >= 0; j--)
6631e4b17023SJohn Marino count_reg_usage (XVECEXP (x, i, j), counts, dest, incr);
6632e4b17023SJohn Marino }
6633e4b17023SJohn Marino }
6634e4b17023SJohn Marino
6635e4b17023SJohn Marino /* Return true if X is a dead register. */
6636e4b17023SJohn Marino
6637e4b17023SJohn Marino static inline int
is_dead_reg(rtx x,int * counts)6638e4b17023SJohn Marino is_dead_reg (rtx x, int *counts)
6639e4b17023SJohn Marino {
6640e4b17023SJohn Marino return (REG_P (x)
6641e4b17023SJohn Marino && REGNO (x) >= FIRST_PSEUDO_REGISTER
6642e4b17023SJohn Marino && counts[REGNO (x)] == 0);
6643e4b17023SJohn Marino }
6644e4b17023SJohn Marino
6645e4b17023SJohn Marino /* Return true if set is live. */
6646e4b17023SJohn Marino static bool
set_live_p(rtx set,rtx insn ATTRIBUTE_UNUSED,int * counts)6647e4b17023SJohn Marino set_live_p (rtx set, rtx insn ATTRIBUTE_UNUSED, /* Only used with HAVE_cc0. */
6648e4b17023SJohn Marino int *counts)
6649e4b17023SJohn Marino {
6650e4b17023SJohn Marino #ifdef HAVE_cc0
6651e4b17023SJohn Marino rtx tem;
6652e4b17023SJohn Marino #endif
6653e4b17023SJohn Marino
6654e4b17023SJohn Marino if (set_noop_p (set))
6655e4b17023SJohn Marino ;
6656e4b17023SJohn Marino
6657e4b17023SJohn Marino #ifdef HAVE_cc0
6658e4b17023SJohn Marino else if (GET_CODE (SET_DEST (set)) == CC0
6659e4b17023SJohn Marino && !side_effects_p (SET_SRC (set))
6660e4b17023SJohn Marino && ((tem = next_nonnote_nondebug_insn (insn)) == NULL_RTX
6661e4b17023SJohn Marino || !INSN_P (tem)
6662e4b17023SJohn Marino || !reg_referenced_p (cc0_rtx, PATTERN (tem))))
6663e4b17023SJohn Marino return false;
6664e4b17023SJohn Marino #endif
6665e4b17023SJohn Marino else if (!is_dead_reg (SET_DEST (set), counts)
6666e4b17023SJohn Marino || side_effects_p (SET_SRC (set)))
6667e4b17023SJohn Marino return true;
6668e4b17023SJohn Marino return false;
6669e4b17023SJohn Marino }
6670e4b17023SJohn Marino
6671e4b17023SJohn Marino /* Return true if insn is live. */
6672e4b17023SJohn Marino
6673e4b17023SJohn Marino static bool
insn_live_p(rtx insn,int * counts)6674e4b17023SJohn Marino insn_live_p (rtx insn, int *counts)
6675e4b17023SJohn Marino {
6676e4b17023SJohn Marino int i;
6677e4b17023SJohn Marino if (insn_could_throw_p (insn))
6678e4b17023SJohn Marino return true;
6679e4b17023SJohn Marino else if (GET_CODE (PATTERN (insn)) == SET)
6680e4b17023SJohn Marino return set_live_p (PATTERN (insn), insn, counts);
6681e4b17023SJohn Marino else if (GET_CODE (PATTERN (insn)) == PARALLEL)
6682e4b17023SJohn Marino {
6683e4b17023SJohn Marino for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
6684e4b17023SJohn Marino {
6685e4b17023SJohn Marino rtx elt = XVECEXP (PATTERN (insn), 0, i);
6686e4b17023SJohn Marino
6687e4b17023SJohn Marino if (GET_CODE (elt) == SET)
6688e4b17023SJohn Marino {
6689e4b17023SJohn Marino if (set_live_p (elt, insn, counts))
6690e4b17023SJohn Marino return true;
6691e4b17023SJohn Marino }
6692e4b17023SJohn Marino else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
6693e4b17023SJohn Marino return true;
6694e4b17023SJohn Marino }
6695e4b17023SJohn Marino return false;
6696e4b17023SJohn Marino }
6697e4b17023SJohn Marino else if (DEBUG_INSN_P (insn))
6698e4b17023SJohn Marino {
6699e4b17023SJohn Marino rtx next;
6700e4b17023SJohn Marino
6701e4b17023SJohn Marino for (next = NEXT_INSN (insn); next; next = NEXT_INSN (next))
6702e4b17023SJohn Marino if (NOTE_P (next))
6703e4b17023SJohn Marino continue;
6704e4b17023SJohn Marino else if (!DEBUG_INSN_P (next))
6705e4b17023SJohn Marino return true;
6706e4b17023SJohn Marino else if (INSN_VAR_LOCATION_DECL (insn) == INSN_VAR_LOCATION_DECL (next))
6707e4b17023SJohn Marino return false;
6708e4b17023SJohn Marino
6709e4b17023SJohn Marino return true;
6710e4b17023SJohn Marino }
6711e4b17023SJohn Marino else
6712e4b17023SJohn Marino return true;
6713e4b17023SJohn Marino }
6714e4b17023SJohn Marino
6715e4b17023SJohn Marino /* Count the number of stores into pseudo. Callback for note_stores. */
6716e4b17023SJohn Marino
6717e4b17023SJohn Marino static void
count_stores(rtx x,const_rtx set ATTRIBUTE_UNUSED,void * data)6718e4b17023SJohn Marino count_stores (rtx x, const_rtx set ATTRIBUTE_UNUSED, void *data)
6719e4b17023SJohn Marino {
6720e4b17023SJohn Marino int *counts = (int *) data;
6721e4b17023SJohn Marino if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER)
6722e4b17023SJohn Marino counts[REGNO (x)]++;
6723e4b17023SJohn Marino }
6724e4b17023SJohn Marino
6725e4b17023SJohn Marino struct dead_debug_insn_data
6726e4b17023SJohn Marino {
6727e4b17023SJohn Marino int *counts;
6728e4b17023SJohn Marino rtx *replacements;
6729e4b17023SJohn Marino bool seen_repl;
6730e4b17023SJohn Marino };
6731e4b17023SJohn Marino
6732e4b17023SJohn Marino /* Return if a DEBUG_INSN needs to be reset because some dead
6733e4b17023SJohn Marino pseudo doesn't have a replacement. Callback for for_each_rtx. */
6734e4b17023SJohn Marino
6735e4b17023SJohn Marino static int
is_dead_debug_insn(rtx * loc,void * data)6736e4b17023SJohn Marino is_dead_debug_insn (rtx *loc, void *data)
6737e4b17023SJohn Marino {
6738e4b17023SJohn Marino rtx x = *loc;
6739e4b17023SJohn Marino struct dead_debug_insn_data *ddid = (struct dead_debug_insn_data *) data;
6740e4b17023SJohn Marino
6741e4b17023SJohn Marino if (is_dead_reg (x, ddid->counts))
6742e4b17023SJohn Marino {
6743e4b17023SJohn Marino if (ddid->replacements && ddid->replacements[REGNO (x)] != NULL_RTX)
6744e4b17023SJohn Marino ddid->seen_repl = true;
6745e4b17023SJohn Marino else
6746e4b17023SJohn Marino return 1;
6747e4b17023SJohn Marino }
6748e4b17023SJohn Marino return 0;
6749e4b17023SJohn Marino }
6750e4b17023SJohn Marino
6751e4b17023SJohn Marino /* Replace a dead pseudo in a DEBUG_INSN with replacement DEBUG_EXPR.
6752e4b17023SJohn Marino Callback for simplify_replace_fn_rtx. */
6753e4b17023SJohn Marino
6754e4b17023SJohn Marino static rtx
replace_dead_reg(rtx x,const_rtx old_rtx ATTRIBUTE_UNUSED,void * data)6755e4b17023SJohn Marino replace_dead_reg (rtx x, const_rtx old_rtx ATTRIBUTE_UNUSED, void *data)
6756e4b17023SJohn Marino {
6757e4b17023SJohn Marino rtx *replacements = (rtx *) data;
6758e4b17023SJohn Marino
6759e4b17023SJohn Marino if (REG_P (x)
6760e4b17023SJohn Marino && REGNO (x) >= FIRST_PSEUDO_REGISTER
6761e4b17023SJohn Marino && replacements[REGNO (x)] != NULL_RTX)
6762e4b17023SJohn Marino {
6763e4b17023SJohn Marino if (GET_MODE (x) == GET_MODE (replacements[REGNO (x)]))
6764e4b17023SJohn Marino return replacements[REGNO (x)];
6765e4b17023SJohn Marino return lowpart_subreg (GET_MODE (x), replacements[REGNO (x)],
6766e4b17023SJohn Marino GET_MODE (replacements[REGNO (x)]));
6767e4b17023SJohn Marino }
6768e4b17023SJohn Marino return NULL_RTX;
6769e4b17023SJohn Marino }
6770e4b17023SJohn Marino
6771e4b17023SJohn Marino /* Scan all the insns and delete any that are dead; i.e., they store a register
6772e4b17023SJohn Marino that is never used or they copy a register to itself.
6773e4b17023SJohn Marino
6774e4b17023SJohn Marino This is used to remove insns made obviously dead by cse, loop or other
6775e4b17023SJohn Marino optimizations. It improves the heuristics in loop since it won't try to
6776e4b17023SJohn Marino move dead invariants out of loops or make givs for dead quantities. The
6777e4b17023SJohn Marino remaining passes of the compilation are also sped up. */
6778e4b17023SJohn Marino
6779e4b17023SJohn Marino int
delete_trivially_dead_insns(rtx insns,int nreg)6780e4b17023SJohn Marino delete_trivially_dead_insns (rtx insns, int nreg)
6781e4b17023SJohn Marino {
6782e4b17023SJohn Marino int *counts;
6783e4b17023SJohn Marino rtx insn, prev;
6784e4b17023SJohn Marino rtx *replacements = NULL;
6785e4b17023SJohn Marino int ndead = 0;
6786e4b17023SJohn Marino
6787e4b17023SJohn Marino timevar_push (TV_DELETE_TRIVIALLY_DEAD);
6788e4b17023SJohn Marino /* First count the number of times each register is used. */
6789e4b17023SJohn Marino if (MAY_HAVE_DEBUG_INSNS)
6790e4b17023SJohn Marino {
6791e4b17023SJohn Marino counts = XCNEWVEC (int, nreg * 3);
6792e4b17023SJohn Marino for (insn = insns; insn; insn = NEXT_INSN (insn))
6793e4b17023SJohn Marino if (DEBUG_INSN_P (insn))
6794e4b17023SJohn Marino count_reg_usage (INSN_VAR_LOCATION_LOC (insn), counts + nreg,
6795e4b17023SJohn Marino NULL_RTX, 1);
6796e4b17023SJohn Marino else if (INSN_P (insn))
6797e4b17023SJohn Marino {
6798e4b17023SJohn Marino count_reg_usage (insn, counts, NULL_RTX, 1);
6799e4b17023SJohn Marino note_stores (PATTERN (insn), count_stores, counts + nreg * 2);
6800e4b17023SJohn Marino }
6801e4b17023SJohn Marino /* If there can be debug insns, COUNTS are 3 consecutive arrays.
6802e4b17023SJohn Marino First one counts how many times each pseudo is used outside
6803e4b17023SJohn Marino of debug insns, second counts how many times each pseudo is
6804e4b17023SJohn Marino used in debug insns and third counts how many times a pseudo
6805e4b17023SJohn Marino is stored. */
6806e4b17023SJohn Marino }
6807e4b17023SJohn Marino else
6808e4b17023SJohn Marino {
6809e4b17023SJohn Marino counts = XCNEWVEC (int, nreg);
6810e4b17023SJohn Marino for (insn = insns; insn; insn = NEXT_INSN (insn))
6811e4b17023SJohn Marino if (INSN_P (insn))
6812e4b17023SJohn Marino count_reg_usage (insn, counts, NULL_RTX, 1);
6813e4b17023SJohn Marino /* If no debug insns can be present, COUNTS is just an array
6814e4b17023SJohn Marino which counts how many times each pseudo is used. */
6815e4b17023SJohn Marino }
6816e4b17023SJohn Marino /* Go from the last insn to the first and delete insns that only set unused
6817e4b17023SJohn Marino registers or copy a register to itself. As we delete an insn, remove
6818e4b17023SJohn Marino usage counts for registers it uses.
6819e4b17023SJohn Marino
6820e4b17023SJohn Marino The first jump optimization pass may leave a real insn as the last
6821e4b17023SJohn Marino insn in the function. We must not skip that insn or we may end
6822e4b17023SJohn Marino up deleting code that is not really dead.
6823e4b17023SJohn Marino
6824e4b17023SJohn Marino If some otherwise unused register is only used in DEBUG_INSNs,
6825e4b17023SJohn Marino try to create a DEBUG_EXPR temporary and emit a DEBUG_INSN before
6826e4b17023SJohn Marino the setter. Then go through DEBUG_INSNs and if a DEBUG_EXPR
6827e4b17023SJohn Marino has been created for the unused register, replace it with
6828e4b17023SJohn Marino the DEBUG_EXPR, otherwise reset the DEBUG_INSN. */
6829e4b17023SJohn Marino for (insn = get_last_insn (); insn; insn = prev)
6830e4b17023SJohn Marino {
6831e4b17023SJohn Marino int live_insn = 0;
6832e4b17023SJohn Marino
6833e4b17023SJohn Marino prev = PREV_INSN (insn);
6834e4b17023SJohn Marino if (!INSN_P (insn))
6835e4b17023SJohn Marino continue;
6836e4b17023SJohn Marino
6837e4b17023SJohn Marino live_insn = insn_live_p (insn, counts);
6838e4b17023SJohn Marino
6839e4b17023SJohn Marino /* If this is a dead insn, delete it and show registers in it aren't
6840e4b17023SJohn Marino being used. */
6841e4b17023SJohn Marino
6842e4b17023SJohn Marino if (! live_insn && dbg_cnt (delete_trivial_dead))
6843e4b17023SJohn Marino {
6844e4b17023SJohn Marino if (DEBUG_INSN_P (insn))
6845e4b17023SJohn Marino count_reg_usage (INSN_VAR_LOCATION_LOC (insn), counts + nreg,
6846e4b17023SJohn Marino NULL_RTX, -1);
6847e4b17023SJohn Marino else
6848e4b17023SJohn Marino {
6849e4b17023SJohn Marino rtx set;
6850e4b17023SJohn Marino if (MAY_HAVE_DEBUG_INSNS
6851e4b17023SJohn Marino && (set = single_set (insn)) != NULL_RTX
6852e4b17023SJohn Marino && is_dead_reg (SET_DEST (set), counts)
6853e4b17023SJohn Marino /* Used at least once in some DEBUG_INSN. */
6854e4b17023SJohn Marino && counts[REGNO (SET_DEST (set)) + nreg] > 0
6855e4b17023SJohn Marino /* And set exactly once. */
6856e4b17023SJohn Marino && counts[REGNO (SET_DEST (set)) + nreg * 2] == 1
6857e4b17023SJohn Marino && !side_effects_p (SET_SRC (set))
6858e4b17023SJohn Marino && asm_noperands (PATTERN (insn)) < 0)
6859e4b17023SJohn Marino {
6860e4b17023SJohn Marino rtx dval, bind;
6861e4b17023SJohn Marino
6862e4b17023SJohn Marino /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL). */
6863e4b17023SJohn Marino dval = make_debug_expr_from_rtl (SET_DEST (set));
6864e4b17023SJohn Marino
6865e4b17023SJohn Marino /* Emit a debug bind insn before the insn in which
6866e4b17023SJohn Marino reg dies. */
6867e4b17023SJohn Marino bind = gen_rtx_VAR_LOCATION (GET_MODE (SET_DEST (set)),
6868e4b17023SJohn Marino DEBUG_EXPR_TREE_DECL (dval),
6869e4b17023SJohn Marino SET_SRC (set),
6870e4b17023SJohn Marino VAR_INIT_STATUS_INITIALIZED);
6871e4b17023SJohn Marino count_reg_usage (bind, counts + nreg, NULL_RTX, 1);
6872e4b17023SJohn Marino
6873e4b17023SJohn Marino bind = emit_debug_insn_before (bind, insn);
6874e4b17023SJohn Marino df_insn_rescan (bind);
6875e4b17023SJohn Marino
6876e4b17023SJohn Marino if (replacements == NULL)
6877e4b17023SJohn Marino replacements = XCNEWVEC (rtx, nreg);
6878e4b17023SJohn Marino replacements[REGNO (SET_DEST (set))] = dval;
6879e4b17023SJohn Marino }
6880e4b17023SJohn Marino
6881e4b17023SJohn Marino count_reg_usage (insn, counts, NULL_RTX, -1);
6882e4b17023SJohn Marino ndead++;
6883e4b17023SJohn Marino }
6884e4b17023SJohn Marino delete_insn_and_edges (insn);
6885e4b17023SJohn Marino }
6886e4b17023SJohn Marino }
6887e4b17023SJohn Marino
6888e4b17023SJohn Marino if (MAY_HAVE_DEBUG_INSNS)
6889e4b17023SJohn Marino {
6890e4b17023SJohn Marino struct dead_debug_insn_data ddid;
6891e4b17023SJohn Marino ddid.counts = counts;
6892e4b17023SJohn Marino ddid.replacements = replacements;
6893e4b17023SJohn Marino for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
6894e4b17023SJohn Marino if (DEBUG_INSN_P (insn))
6895e4b17023SJohn Marino {
6896e4b17023SJohn Marino /* If this debug insn references a dead register that wasn't replaced
6897e4b17023SJohn Marino with an DEBUG_EXPR, reset the DEBUG_INSN. */
6898e4b17023SJohn Marino ddid.seen_repl = false;
6899e4b17023SJohn Marino if (for_each_rtx (&INSN_VAR_LOCATION_LOC (insn),
6900e4b17023SJohn Marino is_dead_debug_insn, &ddid))
6901e4b17023SJohn Marino {
6902e4b17023SJohn Marino INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
6903e4b17023SJohn Marino df_insn_rescan (insn);
6904e4b17023SJohn Marino }
6905e4b17023SJohn Marino else if (ddid.seen_repl)
6906e4b17023SJohn Marino {
6907e4b17023SJohn Marino INSN_VAR_LOCATION_LOC (insn)
6908e4b17023SJohn Marino = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn),
6909e4b17023SJohn Marino NULL_RTX, replace_dead_reg,
6910e4b17023SJohn Marino replacements);
6911e4b17023SJohn Marino df_insn_rescan (insn);
6912e4b17023SJohn Marino }
6913e4b17023SJohn Marino }
6914e4b17023SJohn Marino free (replacements);
6915e4b17023SJohn Marino }
6916e4b17023SJohn Marino
6917e4b17023SJohn Marino if (dump_file && ndead)
6918e4b17023SJohn Marino fprintf (dump_file, "Deleted %i trivially dead insns\n",
6919e4b17023SJohn Marino ndead);
6920e4b17023SJohn Marino /* Clean up. */
6921e4b17023SJohn Marino free (counts);
6922e4b17023SJohn Marino timevar_pop (TV_DELETE_TRIVIALLY_DEAD);
6923e4b17023SJohn Marino return ndead;
6924e4b17023SJohn Marino }
6925e4b17023SJohn Marino
6926e4b17023SJohn Marino /* This function is called via for_each_rtx. The argument, NEWREG, is
6927e4b17023SJohn Marino a condition code register with the desired mode. If we are looking
6928e4b17023SJohn Marino at the same register in a different mode, replace it with
6929e4b17023SJohn Marino NEWREG. */
6930e4b17023SJohn Marino
6931e4b17023SJohn Marino static int
cse_change_cc_mode(rtx * loc,void * data)6932e4b17023SJohn Marino cse_change_cc_mode (rtx *loc, void *data)
6933e4b17023SJohn Marino {
6934e4b17023SJohn Marino struct change_cc_mode_args* args = (struct change_cc_mode_args*)data;
6935e4b17023SJohn Marino
6936e4b17023SJohn Marino if (*loc
6937e4b17023SJohn Marino && REG_P (*loc)
6938e4b17023SJohn Marino && REGNO (*loc) == REGNO (args->newreg)
6939e4b17023SJohn Marino && GET_MODE (*loc) != GET_MODE (args->newreg))
6940e4b17023SJohn Marino {
6941e4b17023SJohn Marino validate_change (args->insn, loc, args->newreg, 1);
6942e4b17023SJohn Marino
6943e4b17023SJohn Marino return -1;
6944e4b17023SJohn Marino }
6945e4b17023SJohn Marino return 0;
6946e4b17023SJohn Marino }
6947e4b17023SJohn Marino
6948e4b17023SJohn Marino /* Change the mode of any reference to the register REGNO (NEWREG) to
6949e4b17023SJohn Marino GET_MODE (NEWREG) in INSN. */
6950e4b17023SJohn Marino
6951e4b17023SJohn Marino static void
cse_change_cc_mode_insn(rtx insn,rtx newreg)6952e4b17023SJohn Marino cse_change_cc_mode_insn (rtx insn, rtx newreg)
6953e4b17023SJohn Marino {
6954e4b17023SJohn Marino struct change_cc_mode_args args;
6955e4b17023SJohn Marino int success;
6956e4b17023SJohn Marino
6957e4b17023SJohn Marino if (!INSN_P (insn))
6958e4b17023SJohn Marino return;
6959e4b17023SJohn Marino
6960e4b17023SJohn Marino args.insn = insn;
6961e4b17023SJohn Marino args.newreg = newreg;
6962e4b17023SJohn Marino
6963e4b17023SJohn Marino for_each_rtx (&PATTERN (insn), cse_change_cc_mode, &args);
6964e4b17023SJohn Marino for_each_rtx (®_NOTES (insn), cse_change_cc_mode, &args);
6965e4b17023SJohn Marino
6966e4b17023SJohn Marino /* If the following assertion was triggered, there is most probably
6967e4b17023SJohn Marino something wrong with the cc_modes_compatible back end function.
6968e4b17023SJohn Marino CC modes only can be considered compatible if the insn - with the mode
6969e4b17023SJohn Marino replaced by any of the compatible modes - can still be recognized. */
6970e4b17023SJohn Marino success = apply_change_group ();
6971e4b17023SJohn Marino gcc_assert (success);
6972e4b17023SJohn Marino }
6973e4b17023SJohn Marino
6974e4b17023SJohn Marino /* Change the mode of any reference to the register REGNO (NEWREG) to
6975e4b17023SJohn Marino GET_MODE (NEWREG), starting at START. Stop before END. Stop at
6976e4b17023SJohn Marino any instruction which modifies NEWREG. */
6977e4b17023SJohn Marino
6978e4b17023SJohn Marino static void
cse_change_cc_mode_insns(rtx start,rtx end,rtx newreg)6979e4b17023SJohn Marino cse_change_cc_mode_insns (rtx start, rtx end, rtx newreg)
6980e4b17023SJohn Marino {
6981e4b17023SJohn Marino rtx insn;
6982e4b17023SJohn Marino
6983e4b17023SJohn Marino for (insn = start; insn != end; insn = NEXT_INSN (insn))
6984e4b17023SJohn Marino {
6985e4b17023SJohn Marino if (! INSN_P (insn))
6986e4b17023SJohn Marino continue;
6987e4b17023SJohn Marino
6988e4b17023SJohn Marino if (reg_set_p (newreg, insn))
6989e4b17023SJohn Marino return;
6990e4b17023SJohn Marino
6991e4b17023SJohn Marino cse_change_cc_mode_insn (insn, newreg);
6992e4b17023SJohn Marino }
6993e4b17023SJohn Marino }
6994e4b17023SJohn Marino
6995e4b17023SJohn Marino /* BB is a basic block which finishes with CC_REG as a condition code
6996e4b17023SJohn Marino register which is set to CC_SRC. Look through the successors of BB
6997e4b17023SJohn Marino to find blocks which have a single predecessor (i.e., this one),
6998e4b17023SJohn Marino and look through those blocks for an assignment to CC_REG which is
6999e4b17023SJohn Marino equivalent to CC_SRC. CAN_CHANGE_MODE indicates whether we are
7000e4b17023SJohn Marino permitted to change the mode of CC_SRC to a compatible mode. This
7001e4b17023SJohn Marino returns VOIDmode if no equivalent assignments were found.
7002e4b17023SJohn Marino Otherwise it returns the mode which CC_SRC should wind up with.
7003e4b17023SJohn Marino ORIG_BB should be the same as BB in the outermost cse_cc_succs call,
7004e4b17023SJohn Marino but is passed unmodified down to recursive calls in order to prevent
7005e4b17023SJohn Marino endless recursion.
7006e4b17023SJohn Marino
7007e4b17023SJohn Marino The main complexity in this function is handling the mode issues.
7008e4b17023SJohn Marino We may have more than one duplicate which we can eliminate, and we
7009e4b17023SJohn Marino try to find a mode which will work for multiple duplicates. */
7010e4b17023SJohn Marino
7011e4b17023SJohn Marino static enum machine_mode
cse_cc_succs(basic_block bb,basic_block orig_bb,rtx cc_reg,rtx cc_src,bool can_change_mode)7012e4b17023SJohn Marino cse_cc_succs (basic_block bb, basic_block orig_bb, rtx cc_reg, rtx cc_src,
7013e4b17023SJohn Marino bool can_change_mode)
7014e4b17023SJohn Marino {
7015e4b17023SJohn Marino bool found_equiv;
7016e4b17023SJohn Marino enum machine_mode mode;
7017e4b17023SJohn Marino unsigned int insn_count;
7018e4b17023SJohn Marino edge e;
7019e4b17023SJohn Marino rtx insns[2];
7020e4b17023SJohn Marino enum machine_mode modes[2];
7021e4b17023SJohn Marino rtx last_insns[2];
7022e4b17023SJohn Marino unsigned int i;
7023e4b17023SJohn Marino rtx newreg;
7024e4b17023SJohn Marino edge_iterator ei;
7025e4b17023SJohn Marino
7026e4b17023SJohn Marino /* We expect to have two successors. Look at both before picking
7027e4b17023SJohn Marino the final mode for the comparison. If we have more successors
7028e4b17023SJohn Marino (i.e., some sort of table jump, although that seems unlikely),
7029e4b17023SJohn Marino then we require all beyond the first two to use the same
7030e4b17023SJohn Marino mode. */
7031e4b17023SJohn Marino
7032e4b17023SJohn Marino found_equiv = false;
7033e4b17023SJohn Marino mode = GET_MODE (cc_src);
7034e4b17023SJohn Marino insn_count = 0;
7035e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs)
7036e4b17023SJohn Marino {
7037e4b17023SJohn Marino rtx insn;
7038e4b17023SJohn Marino rtx end;
7039e4b17023SJohn Marino
7040e4b17023SJohn Marino if (e->flags & EDGE_COMPLEX)
7041e4b17023SJohn Marino continue;
7042e4b17023SJohn Marino
7043e4b17023SJohn Marino if (EDGE_COUNT (e->dest->preds) != 1
7044e4b17023SJohn Marino || e->dest == EXIT_BLOCK_PTR
7045e4b17023SJohn Marino /* Avoid endless recursion on unreachable blocks. */
7046e4b17023SJohn Marino || e->dest == orig_bb)
7047e4b17023SJohn Marino continue;
7048e4b17023SJohn Marino
7049e4b17023SJohn Marino end = NEXT_INSN (BB_END (e->dest));
7050e4b17023SJohn Marino for (insn = BB_HEAD (e->dest); insn != end; insn = NEXT_INSN (insn))
7051e4b17023SJohn Marino {
7052e4b17023SJohn Marino rtx set;
7053e4b17023SJohn Marino
7054e4b17023SJohn Marino if (! INSN_P (insn))
7055e4b17023SJohn Marino continue;
7056e4b17023SJohn Marino
7057e4b17023SJohn Marino /* If CC_SRC is modified, we have to stop looking for
7058e4b17023SJohn Marino something which uses it. */
7059e4b17023SJohn Marino if (modified_in_p (cc_src, insn))
7060e4b17023SJohn Marino break;
7061e4b17023SJohn Marino
7062e4b17023SJohn Marino /* Check whether INSN sets CC_REG to CC_SRC. */
7063e4b17023SJohn Marino set = single_set (insn);
7064e4b17023SJohn Marino if (set
7065e4b17023SJohn Marino && REG_P (SET_DEST (set))
7066e4b17023SJohn Marino && REGNO (SET_DEST (set)) == REGNO (cc_reg))
7067e4b17023SJohn Marino {
7068e4b17023SJohn Marino bool found;
7069e4b17023SJohn Marino enum machine_mode set_mode;
7070e4b17023SJohn Marino enum machine_mode comp_mode;
7071e4b17023SJohn Marino
7072e4b17023SJohn Marino found = false;
7073e4b17023SJohn Marino set_mode = GET_MODE (SET_SRC (set));
7074e4b17023SJohn Marino comp_mode = set_mode;
7075e4b17023SJohn Marino if (rtx_equal_p (cc_src, SET_SRC (set)))
7076e4b17023SJohn Marino found = true;
7077e4b17023SJohn Marino else if (GET_CODE (cc_src) == COMPARE
7078e4b17023SJohn Marino && GET_CODE (SET_SRC (set)) == COMPARE
7079e4b17023SJohn Marino && mode != set_mode
7080e4b17023SJohn Marino && rtx_equal_p (XEXP (cc_src, 0),
7081e4b17023SJohn Marino XEXP (SET_SRC (set), 0))
7082e4b17023SJohn Marino && rtx_equal_p (XEXP (cc_src, 1),
7083e4b17023SJohn Marino XEXP (SET_SRC (set), 1)))
7084e4b17023SJohn Marino
7085e4b17023SJohn Marino {
7086e4b17023SJohn Marino comp_mode = targetm.cc_modes_compatible (mode, set_mode);
7087e4b17023SJohn Marino if (comp_mode != VOIDmode
7088e4b17023SJohn Marino && (can_change_mode || comp_mode == mode))
7089e4b17023SJohn Marino found = true;
7090e4b17023SJohn Marino }
7091e4b17023SJohn Marino
7092e4b17023SJohn Marino if (found)
7093e4b17023SJohn Marino {
7094e4b17023SJohn Marino found_equiv = true;
7095e4b17023SJohn Marino if (insn_count < ARRAY_SIZE (insns))
7096e4b17023SJohn Marino {
7097e4b17023SJohn Marino insns[insn_count] = insn;
7098e4b17023SJohn Marino modes[insn_count] = set_mode;
7099e4b17023SJohn Marino last_insns[insn_count] = end;
7100e4b17023SJohn Marino ++insn_count;
7101e4b17023SJohn Marino
7102e4b17023SJohn Marino if (mode != comp_mode)
7103e4b17023SJohn Marino {
7104e4b17023SJohn Marino gcc_assert (can_change_mode);
7105e4b17023SJohn Marino mode = comp_mode;
7106e4b17023SJohn Marino
7107e4b17023SJohn Marino /* The modified insn will be re-recognized later. */
7108e4b17023SJohn Marino PUT_MODE (cc_src, mode);
7109e4b17023SJohn Marino }
7110e4b17023SJohn Marino }
7111e4b17023SJohn Marino else
7112e4b17023SJohn Marino {
7113e4b17023SJohn Marino if (set_mode != mode)
7114e4b17023SJohn Marino {
7115e4b17023SJohn Marino /* We found a matching expression in the
7116e4b17023SJohn Marino wrong mode, but we don't have room to
7117e4b17023SJohn Marino store it in the array. Punt. This case
7118e4b17023SJohn Marino should be rare. */
7119e4b17023SJohn Marino break;
7120e4b17023SJohn Marino }
7121e4b17023SJohn Marino /* INSN sets CC_REG to a value equal to CC_SRC
7122e4b17023SJohn Marino with the right mode. We can simply delete
7123e4b17023SJohn Marino it. */
7124e4b17023SJohn Marino delete_insn (insn);
7125e4b17023SJohn Marino }
7126e4b17023SJohn Marino
7127e4b17023SJohn Marino /* We found an instruction to delete. Keep looking,
7128e4b17023SJohn Marino in the hopes of finding a three-way jump. */
7129e4b17023SJohn Marino continue;
7130e4b17023SJohn Marino }
7131e4b17023SJohn Marino
7132e4b17023SJohn Marino /* We found an instruction which sets the condition
7133e4b17023SJohn Marino code, so don't look any farther. */
7134e4b17023SJohn Marino break;
7135e4b17023SJohn Marino }
7136e4b17023SJohn Marino
7137e4b17023SJohn Marino /* If INSN sets CC_REG in some other way, don't look any
7138e4b17023SJohn Marino farther. */
7139e4b17023SJohn Marino if (reg_set_p (cc_reg, insn))
7140e4b17023SJohn Marino break;
7141e4b17023SJohn Marino }
7142e4b17023SJohn Marino
7143e4b17023SJohn Marino /* If we fell off the bottom of the block, we can keep looking
7144e4b17023SJohn Marino through successors. We pass CAN_CHANGE_MODE as false because
7145e4b17023SJohn Marino we aren't prepared to handle compatibility between the
7146e4b17023SJohn Marino further blocks and this block. */
7147e4b17023SJohn Marino if (insn == end)
7148e4b17023SJohn Marino {
7149e4b17023SJohn Marino enum machine_mode submode;
7150e4b17023SJohn Marino
7151e4b17023SJohn Marino submode = cse_cc_succs (e->dest, orig_bb, cc_reg, cc_src, false);
7152e4b17023SJohn Marino if (submode != VOIDmode)
7153e4b17023SJohn Marino {
7154e4b17023SJohn Marino gcc_assert (submode == mode);
7155e4b17023SJohn Marino found_equiv = true;
7156e4b17023SJohn Marino can_change_mode = false;
7157e4b17023SJohn Marino }
7158e4b17023SJohn Marino }
7159e4b17023SJohn Marino }
7160e4b17023SJohn Marino
7161e4b17023SJohn Marino if (! found_equiv)
7162e4b17023SJohn Marino return VOIDmode;
7163e4b17023SJohn Marino
7164e4b17023SJohn Marino /* Now INSN_COUNT is the number of instructions we found which set
7165e4b17023SJohn Marino CC_REG to a value equivalent to CC_SRC. The instructions are in
7166e4b17023SJohn Marino INSNS. The modes used by those instructions are in MODES. */
7167e4b17023SJohn Marino
7168e4b17023SJohn Marino newreg = NULL_RTX;
7169e4b17023SJohn Marino for (i = 0; i < insn_count; ++i)
7170e4b17023SJohn Marino {
7171e4b17023SJohn Marino if (modes[i] != mode)
7172e4b17023SJohn Marino {
7173e4b17023SJohn Marino /* We need to change the mode of CC_REG in INSNS[i] and
7174e4b17023SJohn Marino subsequent instructions. */
7175e4b17023SJohn Marino if (! newreg)
7176e4b17023SJohn Marino {
7177e4b17023SJohn Marino if (GET_MODE (cc_reg) == mode)
7178e4b17023SJohn Marino newreg = cc_reg;
7179e4b17023SJohn Marino else
7180e4b17023SJohn Marino newreg = gen_rtx_REG (mode, REGNO (cc_reg));
7181e4b17023SJohn Marino }
7182e4b17023SJohn Marino cse_change_cc_mode_insns (NEXT_INSN (insns[i]), last_insns[i],
7183e4b17023SJohn Marino newreg);
7184e4b17023SJohn Marino }
7185e4b17023SJohn Marino
7186e4b17023SJohn Marino delete_insn_and_edges (insns[i]);
7187e4b17023SJohn Marino }
7188e4b17023SJohn Marino
7189e4b17023SJohn Marino return mode;
7190e4b17023SJohn Marino }
7191e4b17023SJohn Marino
7192e4b17023SJohn Marino /* If we have a fixed condition code register (or two), walk through
7193e4b17023SJohn Marino the instructions and try to eliminate duplicate assignments. */
7194e4b17023SJohn Marino
7195e4b17023SJohn Marino static void
cse_condition_code_reg(void)7196e4b17023SJohn Marino cse_condition_code_reg (void)
7197e4b17023SJohn Marino {
7198e4b17023SJohn Marino unsigned int cc_regno_1;
7199e4b17023SJohn Marino unsigned int cc_regno_2;
7200e4b17023SJohn Marino rtx cc_reg_1;
7201e4b17023SJohn Marino rtx cc_reg_2;
7202e4b17023SJohn Marino basic_block bb;
7203e4b17023SJohn Marino
7204e4b17023SJohn Marino if (! targetm.fixed_condition_code_regs (&cc_regno_1, &cc_regno_2))
7205e4b17023SJohn Marino return;
7206e4b17023SJohn Marino
7207e4b17023SJohn Marino cc_reg_1 = gen_rtx_REG (CCmode, cc_regno_1);
7208e4b17023SJohn Marino if (cc_regno_2 != INVALID_REGNUM)
7209e4b17023SJohn Marino cc_reg_2 = gen_rtx_REG (CCmode, cc_regno_2);
7210e4b17023SJohn Marino else
7211e4b17023SJohn Marino cc_reg_2 = NULL_RTX;
7212e4b17023SJohn Marino
7213e4b17023SJohn Marino FOR_EACH_BB (bb)
7214e4b17023SJohn Marino {
7215e4b17023SJohn Marino rtx last_insn;
7216e4b17023SJohn Marino rtx cc_reg;
7217e4b17023SJohn Marino rtx insn;
7218e4b17023SJohn Marino rtx cc_src_insn;
7219e4b17023SJohn Marino rtx cc_src;
7220e4b17023SJohn Marino enum machine_mode mode;
7221e4b17023SJohn Marino enum machine_mode orig_mode;
7222e4b17023SJohn Marino
7223e4b17023SJohn Marino /* Look for blocks which end with a conditional jump based on a
7224e4b17023SJohn Marino condition code register. Then look for the instruction which
7225e4b17023SJohn Marino sets the condition code register. Then look through the
7226e4b17023SJohn Marino successor blocks for instructions which set the condition
7227e4b17023SJohn Marino code register to the same value. There are other possible
7228e4b17023SJohn Marino uses of the condition code register, but these are by far the
7229e4b17023SJohn Marino most common and the ones which we are most likely to be able
7230e4b17023SJohn Marino to optimize. */
7231e4b17023SJohn Marino
7232e4b17023SJohn Marino last_insn = BB_END (bb);
7233e4b17023SJohn Marino if (!JUMP_P (last_insn))
7234e4b17023SJohn Marino continue;
7235e4b17023SJohn Marino
7236e4b17023SJohn Marino if (reg_referenced_p (cc_reg_1, PATTERN (last_insn)))
7237e4b17023SJohn Marino cc_reg = cc_reg_1;
7238e4b17023SJohn Marino else if (cc_reg_2 && reg_referenced_p (cc_reg_2, PATTERN (last_insn)))
7239e4b17023SJohn Marino cc_reg = cc_reg_2;
7240e4b17023SJohn Marino else
7241e4b17023SJohn Marino continue;
7242e4b17023SJohn Marino
7243e4b17023SJohn Marino cc_src_insn = NULL_RTX;
7244e4b17023SJohn Marino cc_src = NULL_RTX;
7245e4b17023SJohn Marino for (insn = PREV_INSN (last_insn);
7246e4b17023SJohn Marino insn && insn != PREV_INSN (BB_HEAD (bb));
7247e4b17023SJohn Marino insn = PREV_INSN (insn))
7248e4b17023SJohn Marino {
7249e4b17023SJohn Marino rtx set;
7250e4b17023SJohn Marino
7251e4b17023SJohn Marino if (! INSN_P (insn))
7252e4b17023SJohn Marino continue;
7253e4b17023SJohn Marino set = single_set (insn);
7254e4b17023SJohn Marino if (set
7255e4b17023SJohn Marino && REG_P (SET_DEST (set))
7256e4b17023SJohn Marino && REGNO (SET_DEST (set)) == REGNO (cc_reg))
7257e4b17023SJohn Marino {
7258e4b17023SJohn Marino cc_src_insn = insn;
7259e4b17023SJohn Marino cc_src = SET_SRC (set);
7260e4b17023SJohn Marino break;
7261e4b17023SJohn Marino }
7262e4b17023SJohn Marino else if (reg_set_p (cc_reg, insn))
7263e4b17023SJohn Marino break;
7264e4b17023SJohn Marino }
7265e4b17023SJohn Marino
7266e4b17023SJohn Marino if (! cc_src_insn)
7267e4b17023SJohn Marino continue;
7268e4b17023SJohn Marino
7269e4b17023SJohn Marino if (modified_between_p (cc_src, cc_src_insn, NEXT_INSN (last_insn)))
7270e4b17023SJohn Marino continue;
7271e4b17023SJohn Marino
7272e4b17023SJohn Marino /* Now CC_REG is a condition code register used for a
7273e4b17023SJohn Marino conditional jump at the end of the block, and CC_SRC, in
7274e4b17023SJohn Marino CC_SRC_INSN, is the value to which that condition code
7275e4b17023SJohn Marino register is set, and CC_SRC is still meaningful at the end of
7276e4b17023SJohn Marino the basic block. */
7277e4b17023SJohn Marino
7278e4b17023SJohn Marino orig_mode = GET_MODE (cc_src);
7279e4b17023SJohn Marino mode = cse_cc_succs (bb, bb, cc_reg, cc_src, true);
7280e4b17023SJohn Marino if (mode != VOIDmode)
7281e4b17023SJohn Marino {
7282e4b17023SJohn Marino gcc_assert (mode == GET_MODE (cc_src));
7283e4b17023SJohn Marino if (mode != orig_mode)
7284e4b17023SJohn Marino {
7285e4b17023SJohn Marino rtx newreg = gen_rtx_REG (mode, REGNO (cc_reg));
7286e4b17023SJohn Marino
7287e4b17023SJohn Marino cse_change_cc_mode_insn (cc_src_insn, newreg);
7288e4b17023SJohn Marino
7289e4b17023SJohn Marino /* Do the same in the following insns that use the
7290e4b17023SJohn Marino current value of CC_REG within BB. */
7291e4b17023SJohn Marino cse_change_cc_mode_insns (NEXT_INSN (cc_src_insn),
7292e4b17023SJohn Marino NEXT_INSN (last_insn),
7293e4b17023SJohn Marino newreg);
7294e4b17023SJohn Marino }
7295e4b17023SJohn Marino }
7296e4b17023SJohn Marino }
7297e4b17023SJohn Marino }
7298e4b17023SJohn Marino
7299e4b17023SJohn Marino
7300e4b17023SJohn Marino /* Perform common subexpression elimination. Nonzero value from
7301e4b17023SJohn Marino `cse_main' means that jumps were simplified and some code may now
7302e4b17023SJohn Marino be unreachable, so do jump optimization again. */
7303e4b17023SJohn Marino static bool
gate_handle_cse(void)7304e4b17023SJohn Marino gate_handle_cse (void)
7305e4b17023SJohn Marino {
7306e4b17023SJohn Marino return optimize > 0;
7307e4b17023SJohn Marino }
7308e4b17023SJohn Marino
7309e4b17023SJohn Marino static unsigned int
rest_of_handle_cse(void)7310e4b17023SJohn Marino rest_of_handle_cse (void)
7311e4b17023SJohn Marino {
7312e4b17023SJohn Marino int tem;
7313e4b17023SJohn Marino
7314e4b17023SJohn Marino if (dump_file)
7315e4b17023SJohn Marino dump_flow_info (dump_file, dump_flags);
7316e4b17023SJohn Marino
7317e4b17023SJohn Marino tem = cse_main (get_insns (), max_reg_num ());
7318e4b17023SJohn Marino
7319e4b17023SJohn Marino /* If we are not running more CSE passes, then we are no longer
7320e4b17023SJohn Marino expecting CSE to be run. But always rerun it in a cheap mode. */
7321e4b17023SJohn Marino cse_not_expected = !flag_rerun_cse_after_loop && !flag_gcse;
7322e4b17023SJohn Marino
7323e4b17023SJohn Marino if (tem == 2)
7324e4b17023SJohn Marino {
7325e4b17023SJohn Marino timevar_push (TV_JUMP);
7326e4b17023SJohn Marino rebuild_jump_labels (get_insns ());
7327e4b17023SJohn Marino cleanup_cfg (0);
7328e4b17023SJohn Marino timevar_pop (TV_JUMP);
7329e4b17023SJohn Marino }
7330e4b17023SJohn Marino else if (tem == 1 || optimize > 1)
7331e4b17023SJohn Marino cleanup_cfg (0);
7332e4b17023SJohn Marino
7333e4b17023SJohn Marino return 0;
7334e4b17023SJohn Marino }
7335e4b17023SJohn Marino
7336e4b17023SJohn Marino struct rtl_opt_pass pass_cse =
7337e4b17023SJohn Marino {
7338e4b17023SJohn Marino {
7339e4b17023SJohn Marino RTL_PASS,
7340e4b17023SJohn Marino "cse1", /* name */
7341e4b17023SJohn Marino gate_handle_cse, /* gate */
7342e4b17023SJohn Marino rest_of_handle_cse, /* execute */
7343e4b17023SJohn Marino NULL, /* sub */
7344e4b17023SJohn Marino NULL, /* next */
7345e4b17023SJohn Marino 0, /* static_pass_number */
7346e4b17023SJohn Marino TV_CSE, /* tv_id */
7347e4b17023SJohn Marino 0, /* properties_required */
7348e4b17023SJohn Marino 0, /* properties_provided */
7349e4b17023SJohn Marino 0, /* properties_destroyed */
7350e4b17023SJohn Marino 0, /* todo_flags_start */
7351e4b17023SJohn Marino TODO_df_finish | TODO_verify_rtl_sharing |
7352e4b17023SJohn Marino TODO_ggc_collect |
7353e4b17023SJohn Marino TODO_verify_flow, /* todo_flags_finish */
7354e4b17023SJohn Marino }
7355e4b17023SJohn Marino };
7356e4b17023SJohn Marino
7357e4b17023SJohn Marino
7358e4b17023SJohn Marino static bool
gate_handle_cse2(void)7359e4b17023SJohn Marino gate_handle_cse2 (void)
7360e4b17023SJohn Marino {
7361e4b17023SJohn Marino return optimize > 0 && flag_rerun_cse_after_loop;
7362e4b17023SJohn Marino }
7363e4b17023SJohn Marino
7364e4b17023SJohn Marino /* Run second CSE pass after loop optimizations. */
7365e4b17023SJohn Marino static unsigned int
rest_of_handle_cse2(void)7366e4b17023SJohn Marino rest_of_handle_cse2 (void)
7367e4b17023SJohn Marino {
7368e4b17023SJohn Marino int tem;
7369e4b17023SJohn Marino
7370e4b17023SJohn Marino if (dump_file)
7371e4b17023SJohn Marino dump_flow_info (dump_file, dump_flags);
7372e4b17023SJohn Marino
7373e4b17023SJohn Marino tem = cse_main (get_insns (), max_reg_num ());
7374e4b17023SJohn Marino
7375e4b17023SJohn Marino /* Run a pass to eliminate duplicated assignments to condition code
7376e4b17023SJohn Marino registers. We have to run this after bypass_jumps, because it
7377e4b17023SJohn Marino makes it harder for that pass to determine whether a jump can be
7378e4b17023SJohn Marino bypassed safely. */
7379e4b17023SJohn Marino cse_condition_code_reg ();
7380e4b17023SJohn Marino
7381e4b17023SJohn Marino delete_trivially_dead_insns (get_insns (), max_reg_num ());
7382e4b17023SJohn Marino
7383e4b17023SJohn Marino if (tem == 2)
7384e4b17023SJohn Marino {
7385e4b17023SJohn Marino timevar_push (TV_JUMP);
7386e4b17023SJohn Marino rebuild_jump_labels (get_insns ());
7387e4b17023SJohn Marino cleanup_cfg (0);
7388e4b17023SJohn Marino timevar_pop (TV_JUMP);
7389e4b17023SJohn Marino }
7390e4b17023SJohn Marino else if (tem == 1)
7391e4b17023SJohn Marino cleanup_cfg (0);
7392e4b17023SJohn Marino
7393e4b17023SJohn Marino cse_not_expected = 1;
7394e4b17023SJohn Marino return 0;
7395e4b17023SJohn Marino }
7396e4b17023SJohn Marino
7397e4b17023SJohn Marino
7398e4b17023SJohn Marino struct rtl_opt_pass pass_cse2 =
7399e4b17023SJohn Marino {
7400e4b17023SJohn Marino {
7401e4b17023SJohn Marino RTL_PASS,
7402e4b17023SJohn Marino "cse2", /* name */
7403e4b17023SJohn Marino gate_handle_cse2, /* gate */
7404e4b17023SJohn Marino rest_of_handle_cse2, /* execute */
7405e4b17023SJohn Marino NULL, /* sub */
7406e4b17023SJohn Marino NULL, /* next */
7407e4b17023SJohn Marino 0, /* static_pass_number */
7408e4b17023SJohn Marino TV_CSE2, /* tv_id */
7409e4b17023SJohn Marino 0, /* properties_required */
7410e4b17023SJohn Marino 0, /* properties_provided */
7411e4b17023SJohn Marino 0, /* properties_destroyed */
7412e4b17023SJohn Marino 0, /* todo_flags_start */
7413e4b17023SJohn Marino TODO_df_finish | TODO_verify_rtl_sharing |
7414e4b17023SJohn Marino TODO_ggc_collect |
7415e4b17023SJohn Marino TODO_verify_flow /* todo_flags_finish */
7416e4b17023SJohn Marino }
7417e4b17023SJohn Marino };
7418e4b17023SJohn Marino
7419e4b17023SJohn Marino static bool
gate_handle_cse_after_global_opts(void)7420e4b17023SJohn Marino gate_handle_cse_after_global_opts (void)
7421e4b17023SJohn Marino {
7422e4b17023SJohn Marino return optimize > 0 && flag_rerun_cse_after_global_opts;
7423e4b17023SJohn Marino }
7424e4b17023SJohn Marino
7425e4b17023SJohn Marino /* Run second CSE pass after loop optimizations. */
7426e4b17023SJohn Marino static unsigned int
rest_of_handle_cse_after_global_opts(void)7427e4b17023SJohn Marino rest_of_handle_cse_after_global_opts (void)
7428e4b17023SJohn Marino {
7429e4b17023SJohn Marino int save_cfj;
7430e4b17023SJohn Marino int tem;
7431e4b17023SJohn Marino
7432e4b17023SJohn Marino /* We only want to do local CSE, so don't follow jumps. */
7433e4b17023SJohn Marino save_cfj = flag_cse_follow_jumps;
7434e4b17023SJohn Marino flag_cse_follow_jumps = 0;
7435e4b17023SJohn Marino
7436e4b17023SJohn Marino rebuild_jump_labels (get_insns ());
7437e4b17023SJohn Marino tem = cse_main (get_insns (), max_reg_num ());
7438e4b17023SJohn Marino purge_all_dead_edges ();
7439e4b17023SJohn Marino delete_trivially_dead_insns (get_insns (), max_reg_num ());
7440e4b17023SJohn Marino
7441e4b17023SJohn Marino cse_not_expected = !flag_rerun_cse_after_loop;
7442e4b17023SJohn Marino
7443e4b17023SJohn Marino /* If cse altered any jumps, rerun jump opts to clean things up. */
7444e4b17023SJohn Marino if (tem == 2)
7445e4b17023SJohn Marino {
7446e4b17023SJohn Marino timevar_push (TV_JUMP);
7447e4b17023SJohn Marino rebuild_jump_labels (get_insns ());
7448e4b17023SJohn Marino cleanup_cfg (0);
7449e4b17023SJohn Marino timevar_pop (TV_JUMP);
7450e4b17023SJohn Marino }
7451e4b17023SJohn Marino else if (tem == 1)
7452e4b17023SJohn Marino cleanup_cfg (0);
7453e4b17023SJohn Marino
7454e4b17023SJohn Marino flag_cse_follow_jumps = save_cfj;
7455e4b17023SJohn Marino return 0;
7456e4b17023SJohn Marino }
7457e4b17023SJohn Marino
7458e4b17023SJohn Marino struct rtl_opt_pass pass_cse_after_global_opts =
7459e4b17023SJohn Marino {
7460e4b17023SJohn Marino {
7461e4b17023SJohn Marino RTL_PASS,
7462e4b17023SJohn Marino "cse_local", /* name */
7463e4b17023SJohn Marino gate_handle_cse_after_global_opts, /* gate */
7464e4b17023SJohn Marino rest_of_handle_cse_after_global_opts, /* execute */
7465e4b17023SJohn Marino NULL, /* sub */
7466e4b17023SJohn Marino NULL, /* next */
7467e4b17023SJohn Marino 0, /* static_pass_number */
7468e4b17023SJohn Marino TV_CSE, /* tv_id */
7469e4b17023SJohn Marino 0, /* properties_required */
7470e4b17023SJohn Marino 0, /* properties_provided */
7471e4b17023SJohn Marino 0, /* properties_destroyed */
7472e4b17023SJohn Marino 0, /* todo_flags_start */
7473e4b17023SJohn Marino TODO_df_finish | TODO_verify_rtl_sharing |
7474e4b17023SJohn Marino TODO_ggc_collect |
7475e4b17023SJohn Marino TODO_verify_flow /* todo_flags_finish */
7476e4b17023SJohn Marino }
7477e4b17023SJohn Marino };
7478