xref: /dragonfly/contrib/gcc-4.7/gcc/cse.c (revision 5ce9237c)
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 = &reg_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 (&REG_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