cse.c revision 48743
118334Speter/* Common subexpression elimination for GNU compiler.
218334Speter   Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
318334Speter
418334SpeterThis file is part of GNU CC.
518334Speter
618334SpeterGNU CC is free software; you can redistribute it and/or modify
718334Speterit under the terms of the GNU General Public License as published by
818334Speterthe Free Software Foundation; either version 2, or (at your option)
918334Speterany later version.
1018334Speter
1118334SpeterGNU CC is distributed in the hope that it will be useful,
1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1418334SpeterGNU General Public License for more details.
1518334Speter
1618334SpeterYou should have received a copy of the GNU General Public License
1718334Speteralong with GNU CC; see the file COPYING.  If not, write to
1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
1918334SpeterBoston, MA 02111-1307, USA.  */
2018334Speter
2118334Speter
2218334Speter#include "config.h"
2318334Speter/* Must precede rtl.h for FFS.  */
2418334Speter#include <stdio.h>
2518334Speter
2618334Speter#include "rtl.h"
2718334Speter#include "regs.h"
2818334Speter#include "hard-reg-set.h"
2918334Speter#include "flags.h"
3018334Speter#include "real.h"
3118334Speter#include "insn-config.h"
3218334Speter#include "recog.h"
3318334Speter
3418334Speter#include <setjmp.h>
3518334Speter
3618334Speter/* The basic idea of common subexpression elimination is to go
3718334Speter   through the code, keeping a record of expressions that would
3818334Speter   have the same value at the current scan point, and replacing
3918334Speter   expressions encountered with the cheapest equivalent expression.
4018334Speter
4118334Speter   It is too complicated to keep track of the different possibilities
4218334Speter   when control paths merge; so, at each label, we forget all that is
4318334Speter   known and start fresh.  This can be described as processing each
4418334Speter   basic block separately.  Note, however, that these are not quite
4518334Speter   the same as the basic blocks found by a later pass and used for
4618334Speter   data flow analysis and register packing.  We do not need to start fresh
4718334Speter   after a conditional jump instruction if there is no label there.
4818334Speter
4918334Speter   We use two data structures to record the equivalent expressions:
5018334Speter   a hash table for most expressions, and several vectors together
5118334Speter   with "quantity numbers" to record equivalent (pseudo) registers.
5218334Speter
5318334Speter   The use of the special data structure for registers is desirable
5418334Speter   because it is faster.  It is possible because registers references
5518334Speter   contain a fairly small number, the register number, taken from
5618334Speter   a contiguously allocated series, and two register references are
5718334Speter   identical if they have the same number.  General expressions
5818334Speter   do not have any such thing, so the only way to retrieve the
5918334Speter   information recorded on an expression other than a register
6018334Speter   is to keep it in a hash table.
6118334Speter
6218334SpeterRegisters and "quantity numbers":
6318334Speter
6418334Speter   At the start of each basic block, all of the (hardware and pseudo)
6518334Speter   registers used in the function are given distinct quantity
6618334Speter   numbers to indicate their contents.  During scan, when the code
6718334Speter   copies one register into another, we copy the quantity number.
6818334Speter   When a register is loaded in any other way, we allocate a new
6918334Speter   quantity number to describe the value generated by this operation.
7018334Speter   `reg_qty' records what quantity a register is currently thought
7118334Speter   of as containing.
7218334Speter
7318334Speter   All real quantity numbers are greater than or equal to `max_reg'.
7418334Speter   If register N has not been assigned a quantity, reg_qty[N] will equal N.
7518334Speter
7618334Speter   Quantity numbers below `max_reg' do not exist and none of the `qty_...'
7718334Speter   variables should be referenced with an index below `max_reg'.
7818334Speter
7918334Speter   We also maintain a bidirectional chain of registers for each
8018334Speter   quantity number.  `qty_first_reg', `qty_last_reg',
8118334Speter   `reg_next_eqv' and `reg_prev_eqv' hold these chains.
8218334Speter
8318334Speter   The first register in a chain is the one whose lifespan is least local.
8418334Speter   Among equals, it is the one that was seen first.
8518334Speter   We replace any equivalent register with that one.
8618334Speter
8718334Speter   If two registers have the same quantity number, it must be true that
8818334Speter   REG expressions with `qty_mode' must be in the hash table for both
8918334Speter   registers and must be in the same class.
9018334Speter
9118334Speter   The converse is not true.  Since hard registers may be referenced in
9218334Speter   any mode, two REG expressions might be equivalent in the hash table
9318334Speter   but not have the same quantity number if the quantity number of one
9418334Speter   of the registers is not the same mode as those expressions.
9518334Speter
9618334SpeterConstants and quantity numbers
9718334Speter
9818334Speter   When a quantity has a known constant value, that value is stored
9918334Speter   in the appropriate element of qty_const.  This is in addition to
10018334Speter   putting the constant in the hash table as is usual for non-regs.
10118334Speter
10218334Speter   Whether a reg or a constant is preferred is determined by the configuration
10318334Speter   macro CONST_COSTS and will often depend on the constant value.  In any
10418334Speter   event, expressions containing constants can be simplified, by fold_rtx.
10518334Speter
10618334Speter   When a quantity has a known nearly constant value (such as an address
10718334Speter   of a stack slot), that value is stored in the appropriate element
10818334Speter   of qty_const.
10918334Speter
11018334Speter   Integer constants don't have a machine mode.  However, cse
11118334Speter   determines the intended machine mode from the destination
11218334Speter   of the instruction that moves the constant.  The machine mode
11318334Speter   is recorded in the hash table along with the actual RTL
11418334Speter   constant expression so that different modes are kept separate.
11518334Speter
11618334SpeterOther expressions:
11718334Speter
11818334Speter   To record known equivalences among expressions in general
11918334Speter   we use a hash table called `table'.  It has a fixed number of buckets
12018334Speter   that contain chains of `struct table_elt' elements for expressions.
12118334Speter   These chains connect the elements whose expressions have the same
12218334Speter   hash codes.
12318334Speter
12418334Speter   Other chains through the same elements connect the elements which
12518334Speter   currently have equivalent values.
12618334Speter
12718334Speter   Register references in an expression are canonicalized before hashing
12818334Speter   the expression.  This is done using `reg_qty' and `qty_first_reg'.
12918334Speter   The hash code of a register reference is computed using the quantity
13018334Speter   number, not the register number.
13118334Speter
13218334Speter   When the value of an expression changes, it is necessary to remove from the
13318334Speter   hash table not just that expression but all expressions whose values
13418334Speter   could be different as a result.
13518334Speter
13618334Speter     1. If the value changing is in memory, except in special cases
13718334Speter     ANYTHING referring to memory could be changed.  That is because
13818334Speter     nobody knows where a pointer does not point.
13918334Speter     The function `invalidate_memory' removes what is necessary.
14018334Speter
14118334Speter     The special cases are when the address is constant or is
14218334Speter     a constant plus a fixed register such as the frame pointer
14318334Speter     or a static chain pointer.  When such addresses are stored in,
14418334Speter     we can tell exactly which other such addresses must be invalidated
14518334Speter     due to overlap.  `invalidate' does this.
14618334Speter     All expressions that refer to non-constant
14718334Speter     memory addresses are also invalidated.  `invalidate_memory' does this.
14818334Speter
14918334Speter     2. If the value changing is a register, all expressions
15018334Speter     containing references to that register, and only those,
15118334Speter     must be removed.
15218334Speter
15318334Speter   Because searching the entire hash table for expressions that contain
15418334Speter   a register is very slow, we try to figure out when it isn't necessary.
15518334Speter   Precisely, this is necessary only when expressions have been
15618334Speter   entered in the hash table using this register, and then the value has
15718334Speter   changed, and then another expression wants to be added to refer to
15818334Speter   the register's new value.  This sequence of circumstances is rare
15918334Speter   within any one basic block.
16018334Speter
16118334Speter   The vectors `reg_tick' and `reg_in_table' are used to detect this case.
16218334Speter   reg_tick[i] is incremented whenever a value is stored in register i.
16318334Speter   reg_in_table[i] holds -1 if no references to register i have been
16418334Speter   entered in the table; otherwise, it contains the value reg_tick[i] had
16518334Speter   when the references were entered.  If we want to enter a reference
16618334Speter   and reg_in_table[i] != reg_tick[i], we must scan and remove old references.
16718334Speter   Until we want to enter a new entry, the mere fact that the two vectors
16818334Speter   don't match makes the entries be ignored if anyone tries to match them.
16918334Speter
17018334Speter   Registers themselves are entered in the hash table as well as in
17118334Speter   the equivalent-register chains.  However, the vectors `reg_tick'
17218334Speter   and `reg_in_table' do not apply to expressions which are simple
17318334Speter   register references.  These expressions are removed from the table
17418334Speter   immediately when they become invalid, and this can be done even if
17518334Speter   we do not immediately search for all the expressions that refer to
17618334Speter   the register.
17718334Speter
17818334Speter   A CLOBBER rtx in an instruction invalidates its operand for further
17918334Speter   reuse.  A CLOBBER or SET rtx whose operand is a MEM:BLK
18018334Speter   invalidates everything that resides in memory.
18118334Speter
18218334SpeterRelated expressions:
18318334Speter
18418334Speter   Constant expressions that differ only by an additive integer
18518334Speter   are called related.  When a constant expression is put in
18618334Speter   the table, the related expression with no constant term
18718334Speter   is also entered.  These are made to point at each other
18818334Speter   so that it is possible to find out if there exists any
18918334Speter   register equivalent to an expression related to a given expression.  */
19018334Speter
19118334Speter/* One plus largest register number used in this function.  */
19218334Speter
19318334Speterstatic int max_reg;
19418334Speter
19518334Speter/* Length of vectors indexed by quantity number.
19618334Speter   We know in advance we will not need a quantity number this big.  */
19718334Speter
19818334Speterstatic int max_qty;
19918334Speter
20018334Speter/* Next quantity number to be allocated.
20118334Speter   This is 1 + the largest number needed so far.  */
20218334Speter
20318334Speterstatic int next_qty;
20418334Speter
20518334Speter/* Indexed by quantity number, gives the first (or last) (pseudo) register
20618334Speter   in the chain of registers that currently contain this quantity.  */
20718334Speter
20818334Speterstatic int *qty_first_reg;
20918334Speterstatic int *qty_last_reg;
21018334Speter
21118334Speter/* Index by quantity number, gives the mode of the quantity.  */
21218334Speter
21318334Speterstatic enum machine_mode *qty_mode;
21418334Speter
21518334Speter/* Indexed by quantity number, gives the rtx of the constant value of the
21618334Speter   quantity, or zero if it does not have a known value.
21718334Speter   A sum of the frame pointer (or arg pointer) plus a constant
21818334Speter   can also be entered here.  */
21918334Speter
22018334Speterstatic rtx *qty_const;
22118334Speter
22218334Speter/* Indexed by qty number, gives the insn that stored the constant value
22318334Speter   recorded in `qty_const'.  */
22418334Speter
22518334Speterstatic rtx *qty_const_insn;
22618334Speter
22718334Speter/* The next three variables are used to track when a comparison between a
22818334Speter   quantity and some constant or register has been passed.  In that case, we
22918334Speter   know the results of the comparison in case we see it again.  These variables
23018334Speter   record a comparison that is known to be true.  */
23118334Speter
23218334Speter/* Indexed by qty number, gives the rtx code of a comparison with a known
23318334Speter   result involving this quantity.  If none, it is UNKNOWN.  */
23418334Speterstatic enum rtx_code *qty_comparison_code;
23518334Speter
23618334Speter/* Indexed by qty number, gives the constant being compared against in a
23718334Speter   comparison of known result.  If no such comparison, it is undefined.
23818334Speter   If the comparison is not with a constant, it is zero.  */
23918334Speter
24018334Speterstatic rtx *qty_comparison_const;
24118334Speter
24218334Speter/* Indexed by qty number, gives the quantity being compared against in a
24318334Speter   comparison of known result.  If no such comparison, if it undefined.
24418334Speter   If the comparison is not with a register, it is -1.  */
24518334Speter
24618334Speterstatic int *qty_comparison_qty;
24718334Speter
24818334Speter#ifdef HAVE_cc0
24918334Speter/* For machines that have a CC0, we do not record its value in the hash
25018334Speter   table since its use is guaranteed to be the insn immediately following
25118334Speter   its definition and any other insn is presumed to invalidate it.
25218334Speter
25318334Speter   Instead, we store below the value last assigned to CC0.  If it should
25418334Speter   happen to be a constant, it is stored in preference to the actual
25518334Speter   assigned value.  In case it is a constant, we store the mode in which
25618334Speter   the constant should be interpreted.  */
25718334Speter
25818334Speterstatic rtx prev_insn_cc0;
25918334Speterstatic enum machine_mode prev_insn_cc0_mode;
26018334Speter#endif
26118334Speter
26218334Speter/* Previous actual insn.  0 if at first insn of basic block.  */
26318334Speter
26418334Speterstatic rtx prev_insn;
26518334Speter
26618334Speter/* Insn being scanned.  */
26718334Speter
26818334Speterstatic rtx this_insn;
26918334Speter
27018334Speter/* Index by (pseudo) register number, gives the quantity number
27118334Speter   of the register's current contents.  */
27218334Speter
27318334Speterstatic int *reg_qty;
27418334Speter
27518334Speter/* Index by (pseudo) register number, gives the number of the next (or
27618334Speter   previous) (pseudo) register in the chain of registers sharing the same
27718334Speter   value.
27818334Speter
27918334Speter   Or -1 if this register is at the end of the chain.
28018334Speter
28118334Speter   If reg_qty[N] == N, reg_next_eqv[N] is undefined.  */
28218334Speter
28318334Speterstatic int *reg_next_eqv;
28418334Speterstatic int *reg_prev_eqv;
28518334Speter
28618334Speter/* Index by (pseudo) register number, gives the number of times
28718334Speter   that register has been altered in the current basic block.  */
28818334Speter
28918334Speterstatic int *reg_tick;
29018334Speter
29118334Speter/* Index by (pseudo) register number, gives the reg_tick value at which
29218334Speter   rtx's containing this register are valid in the hash table.
29318334Speter   If this does not equal the current reg_tick value, such expressions
29418334Speter   existing in the hash table are invalid.
29518334Speter   If this is -1, no expressions containing this register have been
29618334Speter   entered in the table.  */
29718334Speter
29818334Speterstatic int *reg_in_table;
29918334Speter
30018334Speter/* A HARD_REG_SET containing all the hard registers for which there is
30118334Speter   currently a REG expression in the hash table.  Note the difference
30218334Speter   from the above variables, which indicate if the REG is mentioned in some
30318334Speter   expression in the table.  */
30418334Speter
30518334Speterstatic HARD_REG_SET hard_regs_in_table;
30618334Speter
30718334Speter/* A HARD_REG_SET containing all the hard registers that are invalidated
30818334Speter   by a CALL_INSN.  */
30918334Speter
31018334Speterstatic HARD_REG_SET regs_invalidated_by_call;
31118334Speter
31218334Speter/* Two vectors of ints:
31318334Speter   one containing max_reg -1's; the other max_reg + 500 (an approximation
31418334Speter   for max_qty) elements where element i contains i.
31518334Speter   These are used to initialize various other vectors fast.  */
31618334Speter
31718334Speterstatic int *all_minus_one;
31818334Speterstatic int *consec_ints;
31918334Speter
32018334Speter/* CUID of insn that starts the basic block currently being cse-processed.  */
32118334Speter
32218334Speterstatic int cse_basic_block_start;
32318334Speter
32418334Speter/* CUID of insn that ends the basic block currently being cse-processed.  */
32518334Speter
32618334Speterstatic int cse_basic_block_end;
32718334Speter
32818334Speter/* Vector mapping INSN_UIDs to cuids.
32918334Speter   The cuids are like uids but increase monotonically always.
33018334Speter   We use them to see whether a reg is used outside a given basic block.  */
33118334Speter
33218334Speterstatic int *uid_cuid;
33318334Speter
33418334Speter/* Highest UID in UID_CUID.  */
33518334Speterstatic int max_uid;
33618334Speter
33718334Speter/* Get the cuid of an insn.  */
33818334Speter
33918334Speter#define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)])
34018334Speter
34118334Speter/* Nonzero if cse has altered conditional jump insns
34218334Speter   in such a way that jump optimization should be redone.  */
34318334Speter
34418334Speterstatic int cse_jumps_altered;
34518334Speter
34618334Speter/* Nonzero if we put a LABEL_REF into the hash table.  Since we may have put
34718334Speter   it into an INSN without a REG_LABEL, we have to rerun jump after CSE
34818334Speter   to put in the note.  */
34918334Speterstatic int recorded_label_ref;
35018334Speter
35118334Speter/* canon_hash stores 1 in do_not_record
35218334Speter   if it notices a reference to CC0, PC, or some other volatile
35318334Speter   subexpression.  */
35418334Speter
35518334Speterstatic int do_not_record;
35618334Speter
35718334Speter#ifdef LOAD_EXTEND_OP
35818334Speter
35918334Speter/* Scratch rtl used when looking for load-extended copy of a MEM.  */
36018334Speterstatic rtx memory_extend_rtx;
36118334Speter#endif
36218334Speter
36318334Speter/* canon_hash stores 1 in hash_arg_in_memory
36418334Speter   if it notices a reference to memory within the expression being hashed.  */
36518334Speter
36618334Speterstatic int hash_arg_in_memory;
36718334Speter
36818334Speter/* canon_hash stores 1 in hash_arg_in_struct
36918334Speter   if it notices a reference to memory that's part of a structure.  */
37018334Speter
37118334Speterstatic int hash_arg_in_struct;
37218334Speter
37318334Speter/* The hash table contains buckets which are chains of `struct table_elt's,
37418334Speter   each recording one expression's information.
37518334Speter   That expression is in the `exp' field.
37618334Speter
37718334Speter   Those elements with the same hash code are chained in both directions
37818334Speter   through the `next_same_hash' and `prev_same_hash' fields.
37918334Speter
38018334Speter   Each set of expressions with equivalent values
38118334Speter   are on a two-way chain through the `next_same_value'
38218334Speter   and `prev_same_value' fields, and all point with
38318334Speter   the `first_same_value' field at the first element in
38418334Speter   that chain.  The chain is in order of increasing cost.
38518334Speter   Each element's cost value is in its `cost' field.
38618334Speter
38718334Speter   The `in_memory' field is nonzero for elements that
38818334Speter   involve any reference to memory.  These elements are removed
38918334Speter   whenever a write is done to an unidentified location in memory.
39018334Speter   To be safe, we assume that a memory address is unidentified unless
39118334Speter   the address is either a symbol constant or a constant plus
39218334Speter   the frame pointer or argument pointer.
39318334Speter
39418334Speter   The `in_struct' field is nonzero for elements that
39518334Speter   involve any reference to memory inside a structure or array.
39618334Speter
39718334Speter   The `related_value' field is used to connect related expressions
39818334Speter   (that differ by adding an integer).
39918334Speter   The related expressions are chained in a circular fashion.
40018334Speter   `related_value' is zero for expressions for which this
40118334Speter   chain is not useful.
40218334Speter
40318334Speter   The `cost' field stores the cost of this element's expression.
40418334Speter
40518334Speter   The `is_const' flag is set if the element is a constant (including
40618334Speter   a fixed address).
40718334Speter
40818334Speter   The `flag' field is used as a temporary during some search routines.
40918334Speter
41018334Speter   The `mode' field is usually the same as GET_MODE (`exp'), but
41118334Speter   if `exp' is a CONST_INT and has no machine mode then the `mode'
41218334Speter   field is the mode it was being used as.  Each constant is
41318334Speter   recorded separately for each mode it is used with.  */
41418334Speter
41518334Speter
41618334Speterstruct table_elt
41718334Speter{
41818334Speter  rtx exp;
41918334Speter  struct table_elt *next_same_hash;
42018334Speter  struct table_elt *prev_same_hash;
42118334Speter  struct table_elt *next_same_value;
42218334Speter  struct table_elt *prev_same_value;
42318334Speter  struct table_elt *first_same_value;
42418334Speter  struct table_elt *related_value;
42518334Speter  int cost;
42618334Speter  enum machine_mode mode;
42718334Speter  char in_memory;
42818334Speter  char in_struct;
42918334Speter  char is_const;
43018334Speter  char flag;
43118334Speter};
43218334Speter
43318334Speter/* We don't want a lot of buckets, because we rarely have very many
43418334Speter   things stored in the hash table, and a lot of buckets slows
43518334Speter   down a lot of loops that happen frequently.  */
43618334Speter#define NBUCKETS 31
43718334Speter
43818334Speter/* Compute hash code of X in mode M.  Special-case case where X is a pseudo
43918334Speter   register (hard registers may require `do_not_record' to be set).  */
44018334Speter
44118334Speter#define HASH(X, M)	\
44218334Speter (GET_CODE (X) == REG && REGNO (X) >= FIRST_PSEUDO_REGISTER	\
44318334Speter  ? (((unsigned) REG << 7) + (unsigned) reg_qty[REGNO (X)]) % NBUCKETS	\
44418334Speter  : canon_hash (X, M) % NBUCKETS)
44518334Speter
44618334Speter/* Determine whether register number N is considered a fixed register for CSE.
44718334Speter   It is desirable to replace other regs with fixed regs, to reduce need for
44818334Speter   non-fixed hard regs.
44918334Speter   A reg wins if it is either the frame pointer or designated as fixed,
45018334Speter   but not if it is an overlapping register.  */
45118334Speter#ifdef OVERLAPPING_REGNO_P
45218334Speter#define FIXED_REGNO_P(N)  \
45318334Speter  (((N) == FRAME_POINTER_REGNUM || (N) == HARD_FRAME_POINTER_REGNUM \
45418334Speter    || fixed_regs[N] || global_regs[N])	  \
45518334Speter   && ! OVERLAPPING_REGNO_P ((N)))
45618334Speter#else
45718334Speter#define FIXED_REGNO_P(N)  \
45818334Speter  ((N) == FRAME_POINTER_REGNUM || (N) == HARD_FRAME_POINTER_REGNUM \
45918334Speter   || fixed_regs[N] || global_regs[N])
46018334Speter#endif
46118334Speter
46218334Speter/* Compute cost of X, as stored in the `cost' field of a table_elt.  Fixed
46318334Speter   hard registers and pointers into the frame are the cheapest with a cost
46418334Speter   of 0.  Next come pseudos with a cost of one and other hard registers with
46518334Speter   a cost of 2.  Aside from these special cases, call `rtx_cost'.  */
46618334Speter
46718334Speter#define CHEAP_REGNO(N) \
46818334Speter  ((N) == FRAME_POINTER_REGNUM || (N) == HARD_FRAME_POINTER_REGNUM 	\
46918334Speter   || (N) == STACK_POINTER_REGNUM || (N) == ARG_POINTER_REGNUM	     	\
47018334Speter   || ((N) >= FIRST_VIRTUAL_REGISTER && (N) <= LAST_VIRTUAL_REGISTER) 	\
47118334Speter   || ((N) < FIRST_PSEUDO_REGISTER					\
47218334Speter       && FIXED_REGNO_P (N) && REGNO_REG_CLASS (N) != NO_REGS))
47318334Speter
47418334Speter/* A register is cheap if it is a user variable assigned to the register
47518334Speter   or if its register number always corresponds to a cheap register.  */
47618334Speter
47718334Speter#define CHEAP_REG(N) \
47818334Speter  ((REG_USERVAR_P (N) && REGNO (N) < FIRST_PSEUDO_REGISTER)	\
47918334Speter   || CHEAP_REGNO (REGNO (N)))
48018334Speter
48118334Speter#define COST(X)						\
48218334Speter  (GET_CODE (X) == REG					\
48318334Speter   ? (CHEAP_REG (X) ? 0					\
48418334Speter      : REGNO (X) >= FIRST_PSEUDO_REGISTER ? 1		\
48518334Speter      : 2)						\
48618334Speter   : rtx_cost (X, SET) * 2)
48718334Speter
48818334Speter/* Determine if the quantity number for register X represents a valid index
48918334Speter   into the `qty_...' variables.  */
49018334Speter
49118334Speter#define REGNO_QTY_VALID_P(N) (reg_qty[N] != (N))
49218334Speter
49318334Speterstatic struct table_elt *table[NBUCKETS];
49418334Speter
49518334Speter/* Chain of `struct table_elt's made so far for this function
49618334Speter   but currently removed from the table.  */
49718334Speter
49818334Speterstatic struct table_elt *free_element_chain;
49918334Speter
50018334Speter/* Number of `struct table_elt' structures made so far for this function.  */
50118334Speter
50218334Speterstatic int n_elements_made;
50318334Speter
50418334Speter/* Maximum value `n_elements_made' has had so far in this compilation
50518334Speter   for functions previously processed.  */
50618334Speter
50718334Speterstatic int max_elements_made;
50818334Speter
50918334Speter/* Surviving equivalence class when two equivalence classes are merged
51018334Speter   by recording the effects of a jump in the last insn.  Zero if the
51118334Speter   last insn was not a conditional jump.  */
51218334Speter
51318334Speterstatic struct table_elt *last_jump_equiv_class;
51418334Speter
51518334Speter/* Set to the cost of a constant pool reference if one was found for a
51618334Speter   symbolic constant.  If this was found, it means we should try to
51718334Speter   convert constants into constant pool entries if they don't fit in
51818334Speter   the insn.  */
51918334Speter
52018334Speterstatic int constant_pool_entries_cost;
52118334Speter
52218334Speter/* Bits describing what kind of values in memory must be invalidated
52318334Speter   for a particular instruction.  If all three bits are zero,
52418334Speter   no memory refs need to be invalidated.  Each bit is more powerful
52518334Speter   than the preceding ones, and if a bit is set then the preceding
52618334Speter   bits are also set.
52718334Speter
52818334Speter   Here is how the bits are set:
52918334Speter   Pushing onto the stack invalidates only the stack pointer,
53018334Speter   writing at a fixed address invalidates only variable addresses,
53118334Speter   writing in a structure element at variable address
53218334Speter     invalidates all but scalar variables,
53318334Speter   and writing in anything else at variable address invalidates everything.  */
53418334Speter
53518334Speterstruct write_data
53618334Speter{
53718334Speter  int sp : 1;			/* Invalidate stack pointer. */
53818334Speter  int var : 1;			/* Invalidate variable addresses.  */
53918334Speter  int nonscalar : 1;		/* Invalidate all but scalar variables.  */
54018334Speter  int all : 1;			/* Invalidate all memory refs.  */
54118334Speter};
54218334Speter
54318334Speter/* Define maximum length of a branch path.  */
54418334Speter
54518334Speter#define PATHLENGTH	10
54618334Speter
54718334Speter/* This data describes a block that will be processed by cse_basic_block.  */
54818334Speter
54918334Speterstruct cse_basic_block_data {
55018334Speter  /* Lowest CUID value of insns in block.  */
55118334Speter  int low_cuid;
55218334Speter  /* Highest CUID value of insns in block.  */
55318334Speter  int high_cuid;
55418334Speter  /* Total number of SETs in block.  */
55518334Speter  int nsets;
55618334Speter  /* Last insn in the block.  */
55718334Speter  rtx last;
55818334Speter  /* Size of current branch path, if any.  */
55918334Speter  int path_size;
56018334Speter  /* Current branch path, indicating which branches will be taken.  */
56118334Speter  struct branch_path {
56218334Speter    /* The branch insn. */
56318334Speter    rtx branch;
56418334Speter    /* Whether it should be taken or not.  AROUND is the same as taken
56518334Speter       except that it is used when the destination label is not preceded
56618334Speter       by a BARRIER.  */
56718334Speter    enum taken {TAKEN, NOT_TAKEN, AROUND} status;
56818334Speter  } path[PATHLENGTH];
56918334Speter};
57018334Speter
57118334Speter/* Nonzero if X has the form (PLUS frame-pointer integer).  We check for
57218334Speter   virtual regs here because the simplify_*_operation routines are called
57318334Speter   by integrate.c, which is called before virtual register instantiation.  */
57418334Speter
57518334Speter#define FIXED_BASE_PLUS_P(X)					\
57618334Speter  ((X) == frame_pointer_rtx || (X) == hard_frame_pointer_rtx	\
57718334Speter   || (X) == arg_pointer_rtx					\
57818334Speter   || (X) == virtual_stack_vars_rtx				\
57918334Speter   || (X) == virtual_incoming_args_rtx				\
58018334Speter   || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
58118334Speter       && (XEXP (X, 0) == frame_pointer_rtx			\
58218334Speter	   || XEXP (X, 0) == hard_frame_pointer_rtx		\
58318334Speter	   || XEXP (X, 0) == arg_pointer_rtx			\
58418334Speter	   || XEXP (X, 0) == virtual_stack_vars_rtx		\
58518334Speter	   || XEXP (X, 0) == virtual_incoming_args_rtx)))
58618334Speter
58718334Speter/* Similar, but also allows reference to the stack pointer.
58818334Speter
58918334Speter   This used to include FIXED_BASE_PLUS_P, however, we can't assume that
59018334Speter   arg_pointer_rtx by itself is nonzero, because on at least one machine,
59118334Speter   the i960, the arg pointer is zero when it is unused.  */
59218334Speter
59318334Speter#define NONZERO_BASE_PLUS_P(X)					\
59418334Speter  ((X) == frame_pointer_rtx || (X) == hard_frame_pointer_rtx	\
59518334Speter   || (X) == virtual_stack_vars_rtx				\
59618334Speter   || (X) == virtual_incoming_args_rtx				\
59718334Speter   || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
59818334Speter       && (XEXP (X, 0) == frame_pointer_rtx			\
59918334Speter	   || XEXP (X, 0) == hard_frame_pointer_rtx		\
60018334Speter	   || XEXP (X, 0) == arg_pointer_rtx			\
60118334Speter	   || XEXP (X, 0) == virtual_stack_vars_rtx		\
60218334Speter	   || XEXP (X, 0) == virtual_incoming_args_rtx))	\
60318334Speter   || (X) == stack_pointer_rtx					\
60418334Speter   || (X) == virtual_stack_dynamic_rtx				\
60518334Speter   || (X) == virtual_outgoing_args_rtx				\
60618334Speter   || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
60718334Speter       && (XEXP (X, 0) == stack_pointer_rtx			\
60818334Speter	   || XEXP (X, 0) == virtual_stack_dynamic_rtx		\
60918334Speter	   || XEXP (X, 0) == virtual_outgoing_args_rtx)))
61018334Speter
61118334Speterstatic void new_basic_block	PROTO((void));
61218334Speterstatic void make_new_qty	PROTO((int));
61318334Speterstatic void make_regs_eqv	PROTO((int, int));
61418334Speterstatic void delete_reg_equiv	PROTO((int));
61518334Speterstatic int mention_regs		PROTO((rtx));
61618334Speterstatic int insert_regs		PROTO((rtx, struct table_elt *, int));
61718334Speterstatic void free_element	PROTO((struct table_elt *));
61818334Speterstatic void remove_from_table	PROTO((struct table_elt *, unsigned));
61918334Speterstatic struct table_elt *get_element PROTO((void));
62018334Speterstatic struct table_elt *lookup	PROTO((rtx, unsigned, enum machine_mode)),
62118334Speter       *lookup_for_remove PROTO((rtx, unsigned, enum machine_mode));
62218334Speterstatic rtx lookup_as_function	PROTO((rtx, enum rtx_code));
62318334Speterstatic struct table_elt *insert PROTO((rtx, struct table_elt *, unsigned,
62418334Speter				       enum machine_mode));
62518334Speterstatic void merge_equiv_classes PROTO((struct table_elt *,
62618334Speter				       struct table_elt *));
62718334Speterstatic void invalidate		PROTO((rtx, enum machine_mode));
62818334Speterstatic void remove_invalid_refs	PROTO((int));
62918334Speterstatic void rehash_using_reg	PROTO((rtx));
63018334Speterstatic void invalidate_memory	PROTO((struct write_data *));
63118334Speterstatic void invalidate_for_call	PROTO((void));
63218334Speterstatic rtx use_related_value	PROTO((rtx, struct table_elt *));
63318334Speterstatic unsigned canon_hash	PROTO((rtx, enum machine_mode));
63418334Speterstatic unsigned safe_hash	PROTO((rtx, enum machine_mode));
63518334Speterstatic int exp_equiv_p		PROTO((rtx, rtx, int, int));
63618334Speterstatic void set_nonvarying_address_components PROTO((rtx, int, rtx *,
63718334Speter						     HOST_WIDE_INT *,
63818334Speter						     HOST_WIDE_INT *));
63918334Speterstatic int refers_to_p		PROTO((rtx, rtx));
64018334Speterstatic int refers_to_mem_p	PROTO((rtx, rtx, HOST_WIDE_INT,
64118334Speter				       HOST_WIDE_INT));
64218334Speterstatic int cse_rtx_addr_varies_p PROTO((rtx));
64318334Speterstatic rtx canon_reg		PROTO((rtx, rtx));
64418334Speterstatic void find_best_addr	PROTO((rtx, rtx *));
64518334Speterstatic enum rtx_code find_comparison_args PROTO((enum rtx_code, rtx *, rtx *,
64618334Speter						 enum machine_mode *,
64718334Speter						 enum machine_mode *));
64818334Speterstatic rtx cse_gen_binary	PROTO((enum rtx_code, enum machine_mode,
64918334Speter				       rtx, rtx));
65018334Speterstatic rtx simplify_plus_minus	PROTO((enum rtx_code, enum machine_mode,
65118334Speter				       rtx, rtx));
65218334Speterstatic rtx fold_rtx		PROTO((rtx, rtx));
65318334Speterstatic rtx equiv_constant	PROTO((rtx));
65418334Speterstatic void record_jump_equiv	PROTO((rtx, int));
65518334Speterstatic void record_jump_cond	PROTO((enum rtx_code, enum machine_mode,
65618334Speter				       rtx, rtx, int));
65718334Speterstatic void cse_insn		PROTO((rtx, int));
65818334Speterstatic void note_mem_written	PROTO((rtx, struct write_data *));
65918334Speterstatic void invalidate_from_clobbers PROTO((struct write_data *, rtx));
66018334Speterstatic rtx cse_process_notes	PROTO((rtx, rtx));
66118334Speterstatic void cse_around_loop	PROTO((rtx));
66218334Speterstatic void invalidate_skipped_set PROTO((rtx, rtx));
66318334Speterstatic void invalidate_skipped_block PROTO((rtx));
66418334Speterstatic void cse_check_loop_start PROTO((rtx, rtx));
66518334Speterstatic void cse_set_around_loop	PROTO((rtx, rtx, rtx));
66618334Speterstatic rtx cse_basic_block	PROTO((rtx, rtx, struct branch_path *, int));
66718334Speterstatic void count_reg_usage	PROTO((rtx, int *, rtx, int));
66818334Speter
66918334Speterextern int rtx_equal_function_value_matters;
67018334Speter
67118334Speter/* Return an estimate of the cost of computing rtx X.
67218334Speter   One use is in cse, to decide which expression to keep in the hash table.
67318334Speter   Another is in rtl generation, to pick the cheapest way to multiply.
67418334Speter   Other uses like the latter are expected in the future.  */
67518334Speter
67618334Speter/* Return the right cost to give to an operation
67718334Speter   to make the cost of the corresponding register-to-register instruction
67818334Speter   N times that of a fast register-to-register instruction.  */
67918334Speter
68018334Speter#define COSTS_N_INSNS(N) ((N) * 4 - 2)
68118334Speter
68218334Speterint
68318334Speterrtx_cost (x, outer_code)
68418334Speter     rtx x;
68518334Speter     enum rtx_code outer_code;
68618334Speter{
68718334Speter  register int i, j;
68818334Speter  register enum rtx_code code;
68918334Speter  register char *fmt;
69018334Speter  register int total;
69118334Speter
69218334Speter  if (x == 0)
69318334Speter    return 0;
69418334Speter
69518334Speter  /* Compute the default costs of certain things.
69618334Speter     Note that RTX_COSTS can override the defaults.  */
69718334Speter
69818334Speter  code = GET_CODE (x);
69918334Speter  switch (code)
70018334Speter    {
70118334Speter    case MULT:
70218334Speter      /* Count multiplication by 2**n as a shift,
70318334Speter	 because if we are considering it, we would output it as a shift.  */
70418334Speter      if (GET_CODE (XEXP (x, 1)) == CONST_INT
70518334Speter	  && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
70618334Speter	total = 2;
70718334Speter      else
70818334Speter	total = COSTS_N_INSNS (5);
70918334Speter      break;
71018334Speter    case DIV:
71118334Speter    case UDIV:
71218334Speter    case MOD:
71318334Speter    case UMOD:
71418334Speter      total = COSTS_N_INSNS (7);
71518334Speter      break;
71618334Speter    case USE:
71718334Speter      /* Used in loop.c and combine.c as a marker.  */
71818334Speter      total = 0;
71918334Speter      break;
72018334Speter    case ASM_OPERANDS:
72118334Speter      /* We don't want these to be used in substitutions because
72218334Speter	 we have no way of validating the resulting insn.  So assign
72318334Speter	 anything containing an ASM_OPERANDS a very high cost.  */
72418334Speter      total = 1000;
72518334Speter      break;
72618334Speter    default:
72718334Speter      total = 2;
72818334Speter    }
72918334Speter
73018334Speter  switch (code)
73118334Speter    {
73218334Speter    case REG:
73318334Speter      return ! CHEAP_REG (x);
73418334Speter
73518334Speter    case SUBREG:
73618334Speter      /* If we can't tie these modes, make this expensive.  The larger
73718334Speter	 the mode, the more expensive it is.  */
73818334Speter      if (! MODES_TIEABLE_P (GET_MODE (x), GET_MODE (SUBREG_REG (x))))
73918334Speter	return COSTS_N_INSNS (2
74018334Speter			      + GET_MODE_SIZE (GET_MODE (x)) / UNITS_PER_WORD);
74118334Speter      return 2;
74218334Speter#ifdef RTX_COSTS
74318334Speter      RTX_COSTS (x, code, outer_code);
74418334Speter#endif
74518334Speter      CONST_COSTS (x, code, outer_code);
74618334Speter    }
74718334Speter
74818334Speter  /* Sum the costs of the sub-rtx's, plus cost of this operation,
74918334Speter     which is already in total.  */
75018334Speter
75118334Speter  fmt = GET_RTX_FORMAT (code);
75218334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
75318334Speter    if (fmt[i] == 'e')
75418334Speter      total += rtx_cost (XEXP (x, i), code);
75518334Speter    else if (fmt[i] == 'E')
75618334Speter      for (j = 0; j < XVECLEN (x, i); j++)
75718334Speter	total += rtx_cost (XVECEXP (x, i, j), code);
75818334Speter
75918334Speter  return total;
76018334Speter}
76118334Speter
76218334Speter/* Clear the hash table and initialize each register with its own quantity,
76318334Speter   for a new basic block.  */
76418334Speter
76518334Speterstatic void
76618334Speternew_basic_block ()
76718334Speter{
76818334Speter  register int i;
76918334Speter
77018334Speter  next_qty = max_reg;
77118334Speter
77218334Speter  bzero ((char *) reg_tick, max_reg * sizeof (int));
77318334Speter
77418334Speter  bcopy ((char *) all_minus_one, (char *) reg_in_table,
77518334Speter	 max_reg * sizeof (int));
77618334Speter  bcopy ((char *) consec_ints, (char *) reg_qty, max_reg * sizeof (int));
77718334Speter  CLEAR_HARD_REG_SET (hard_regs_in_table);
77818334Speter
77918334Speter  /* The per-quantity values used to be initialized here, but it is
78018334Speter     much faster to initialize each as it is made in `make_new_qty'.  */
78118334Speter
78218334Speter  for (i = 0; i < NBUCKETS; i++)
78318334Speter    {
78418334Speter      register struct table_elt *this, *next;
78518334Speter      for (this = table[i]; this; this = next)
78618334Speter	{
78718334Speter	  next = this->next_same_hash;
78818334Speter	  free_element (this);
78918334Speter	}
79018334Speter    }
79118334Speter
79218334Speter  bzero ((char *) table, sizeof table);
79318334Speter
79418334Speter  prev_insn = 0;
79518334Speter
79618334Speter#ifdef HAVE_cc0
79718334Speter  prev_insn_cc0 = 0;
79818334Speter#endif
79918334Speter}
80018334Speter
80118334Speter/* Say that register REG contains a quantity not in any register before
80218334Speter   and initialize that quantity.  */
80318334Speter
80418334Speterstatic void
80518334Spetermake_new_qty (reg)
80618334Speter     register int reg;
80718334Speter{
80818334Speter  register int q;
80918334Speter
81018334Speter  if (next_qty >= max_qty)
81118334Speter    abort ();
81218334Speter
81318334Speter  q = reg_qty[reg] = next_qty++;
81418334Speter  qty_first_reg[q] = reg;
81518334Speter  qty_last_reg[q] = reg;
81618334Speter  qty_const[q] = qty_const_insn[q] = 0;
81718334Speter  qty_comparison_code[q] = UNKNOWN;
81818334Speter
81918334Speter  reg_next_eqv[reg] = reg_prev_eqv[reg] = -1;
82018334Speter}
82118334Speter
82218334Speter/* Make reg NEW equivalent to reg OLD.
82318334Speter   OLD is not changing; NEW is.  */
82418334Speter
82518334Speterstatic void
82618334Spetermake_regs_eqv (new, old)
82718334Speter     register int new, old;
82818334Speter{
82918334Speter  register int lastr, firstr;
83018334Speter  register int q = reg_qty[old];
83118334Speter
83218334Speter  /* Nothing should become eqv until it has a "non-invalid" qty number.  */
83318334Speter  if (! REGNO_QTY_VALID_P (old))
83418334Speter    abort ();
83518334Speter
83618334Speter  reg_qty[new] = q;
83718334Speter  firstr = qty_first_reg[q];
83818334Speter  lastr = qty_last_reg[q];
83918334Speter
84018334Speter  /* Prefer fixed hard registers to anything.  Prefer pseudo regs to other
84118334Speter     hard regs.  Among pseudos, if NEW will live longer than any other reg
84218334Speter     of the same qty, and that is beyond the current basic block,
84318334Speter     make it the new canonical replacement for this qty.  */
84418334Speter  if (! (firstr < FIRST_PSEUDO_REGISTER && FIXED_REGNO_P (firstr))
84518334Speter      /* Certain fixed registers might be of the class NO_REGS.  This means
84618334Speter	 that not only can they not be allocated by the compiler, but
84718334Speter	 they cannot be used in substitutions or canonicalizations
84818334Speter	 either.  */
84918334Speter      && (new >= FIRST_PSEUDO_REGISTER || REGNO_REG_CLASS (new) != NO_REGS)
85018334Speter      && ((new < FIRST_PSEUDO_REGISTER && FIXED_REGNO_P (new))
85118334Speter	  || (new >= FIRST_PSEUDO_REGISTER
85218334Speter	      && (firstr < FIRST_PSEUDO_REGISTER
85318334Speter		  || ((uid_cuid[regno_last_uid[new]] > cse_basic_block_end
85418334Speter		       || (uid_cuid[regno_first_uid[new]]
85518334Speter			   < cse_basic_block_start))
85618334Speter		      && (uid_cuid[regno_last_uid[new]]
85718334Speter			  > uid_cuid[regno_last_uid[firstr]]))))))
85818334Speter    {
85918334Speter      reg_prev_eqv[firstr] = new;
86018334Speter      reg_next_eqv[new] = firstr;
86118334Speter      reg_prev_eqv[new] = -1;
86218334Speter      qty_first_reg[q] = new;
86318334Speter    }
86418334Speter  else
86518334Speter    {
86618334Speter      /* If NEW is a hard reg (known to be non-fixed), insert at end.
86718334Speter	 Otherwise, insert before any non-fixed hard regs that are at the
86818334Speter	 end.  Registers of class NO_REGS cannot be used as an
86918334Speter	 equivalent for anything.  */
87018334Speter      while (lastr < FIRST_PSEUDO_REGISTER && reg_prev_eqv[lastr] >= 0
87118334Speter	     && (REGNO_REG_CLASS (lastr) == NO_REGS || ! FIXED_REGNO_P (lastr))
87218334Speter	     && new >= FIRST_PSEUDO_REGISTER)
87318334Speter	lastr = reg_prev_eqv[lastr];
87418334Speter      reg_next_eqv[new] = reg_next_eqv[lastr];
87518334Speter      if (reg_next_eqv[lastr] >= 0)
87618334Speter	reg_prev_eqv[reg_next_eqv[lastr]] = new;
87718334Speter      else
87818334Speter	qty_last_reg[q] = new;
87918334Speter      reg_next_eqv[lastr] = new;
88018334Speter      reg_prev_eqv[new] = lastr;
88118334Speter    }
88218334Speter}
88318334Speter
88418334Speter/* Remove REG from its equivalence class.  */
88518334Speter
88618334Speterstatic void
88718334Speterdelete_reg_equiv (reg)
88818334Speter     register int reg;
88918334Speter{
89018334Speter  register int q = reg_qty[reg];
89118334Speter  register int p, n;
89218334Speter
89318334Speter  /* If invalid, do nothing.  */
89418334Speter  if (q == reg)
89518334Speter    return;
89618334Speter
89718334Speter  p = reg_prev_eqv[reg];
89818334Speter  n = reg_next_eqv[reg];
89918334Speter
90018334Speter  if (n != -1)
90118334Speter    reg_prev_eqv[n] = p;
90218334Speter  else
90318334Speter    qty_last_reg[q] = p;
90418334Speter  if (p != -1)
90518334Speter    reg_next_eqv[p] = n;
90618334Speter  else
90718334Speter    qty_first_reg[q] = n;
90818334Speter
90918334Speter  reg_qty[reg] = reg;
91018334Speter}
91118334Speter
91218334Speter/* Remove any invalid expressions from the hash table
91318334Speter   that refer to any of the registers contained in expression X.
91418334Speter
91518334Speter   Make sure that newly inserted references to those registers
91618334Speter   as subexpressions will be considered valid.
91718334Speter
91818334Speter   mention_regs is not called when a register itself
91918334Speter   is being stored in the table.
92018334Speter
92118334Speter   Return 1 if we have done something that may have changed the hash code
92218334Speter   of X.  */
92318334Speter
92418334Speterstatic int
92518334Spetermention_regs (x)
92618334Speter     rtx x;
92718334Speter{
92818334Speter  register enum rtx_code code;
92918334Speter  register int i, j;
93018334Speter  register char *fmt;
93118334Speter  register int changed = 0;
93218334Speter
93318334Speter  if (x == 0)
93418334Speter    return 0;
93518334Speter
93618334Speter  code = GET_CODE (x);
93718334Speter  if (code == REG)
93818334Speter    {
93918334Speter      register int regno = REGNO (x);
94018334Speter      register int endregno
94118334Speter	= regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
94218334Speter		   : HARD_REGNO_NREGS (regno, GET_MODE (x)));
94318334Speter      int i;
94418334Speter
94518334Speter      for (i = regno; i < endregno; i++)
94618334Speter	{
94718334Speter	  if (reg_in_table[i] >= 0 && reg_in_table[i] != reg_tick[i])
94818334Speter	    remove_invalid_refs (i);
94918334Speter
95018334Speter	  reg_in_table[i] = reg_tick[i];
95118334Speter	}
95218334Speter
95318334Speter      return 0;
95418334Speter    }
95518334Speter
95618334Speter  /* If X is a comparison or a COMPARE and either operand is a register
95718334Speter     that does not have a quantity, give it one.  This is so that a later
95818334Speter     call to record_jump_equiv won't cause X to be assigned a different
95918334Speter     hash code and not found in the table after that call.
96018334Speter
96118334Speter     It is not necessary to do this here, since rehash_using_reg can
96218334Speter     fix up the table later, but doing this here eliminates the need to
96318334Speter     call that expensive function in the most common case where the only
96418334Speter     use of the register is in the comparison.  */
96518334Speter
96618334Speter  if (code == COMPARE || GET_RTX_CLASS (code) == '<')
96718334Speter    {
96818334Speter      if (GET_CODE (XEXP (x, 0)) == REG
96918334Speter	  && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 0))))
97018334Speter	if (insert_regs (XEXP (x, 0), NULL_PTR, 0))
97118334Speter	  {
97218334Speter	    rehash_using_reg (XEXP (x, 0));
97318334Speter	    changed = 1;
97418334Speter	  }
97518334Speter
97618334Speter      if (GET_CODE (XEXP (x, 1)) == REG
97718334Speter	  && ! REGNO_QTY_VALID_P (REGNO (XEXP (x, 1))))
97818334Speter	if (insert_regs (XEXP (x, 1), NULL_PTR, 0))
97918334Speter	  {
98018334Speter	    rehash_using_reg (XEXP (x, 1));
98118334Speter	    changed = 1;
98218334Speter	  }
98318334Speter    }
98418334Speter
98518334Speter  fmt = GET_RTX_FORMAT (code);
98618334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
98718334Speter    if (fmt[i] == 'e')
98818334Speter      changed |= mention_regs (XEXP (x, i));
98918334Speter    else if (fmt[i] == 'E')
99018334Speter      for (j = 0; j < XVECLEN (x, i); j++)
99118334Speter	changed |= mention_regs (XVECEXP (x, i, j));
99218334Speter
99318334Speter  return changed;
99418334Speter}
99518334Speter
99618334Speter/* Update the register quantities for inserting X into the hash table
99718334Speter   with a value equivalent to CLASSP.
99818334Speter   (If the class does not contain a REG, it is irrelevant.)
99918334Speter   If MODIFIED is nonzero, X is a destination; it is being modified.
100018334Speter   Note that delete_reg_equiv should be called on a register
100118334Speter   before insert_regs is done on that register with MODIFIED != 0.
100218334Speter
100318334Speter   Nonzero value means that elements of reg_qty have changed
100418334Speter   so X's hash code may be different.  */
100518334Speter
100618334Speterstatic int
100718334Speterinsert_regs (x, classp, modified)
100818334Speter     rtx x;
100918334Speter     struct table_elt *classp;
101018334Speter     int modified;
101118334Speter{
101218334Speter  if (GET_CODE (x) == REG)
101318334Speter    {
101418334Speter      register int regno = REGNO (x);
101518334Speter
101618334Speter      /* If REGNO is in the equivalence table already but is of the
101718334Speter	 wrong mode for that equivalence, don't do anything here.  */
101818334Speter
101918334Speter      if (REGNO_QTY_VALID_P (regno)
102018334Speter	  && qty_mode[reg_qty[regno]] != GET_MODE (x))
102118334Speter	return 0;
102218334Speter
102318334Speter      if (modified || ! REGNO_QTY_VALID_P (regno))
102418334Speter	{
102518334Speter	  if (classp)
102618334Speter	    for (classp = classp->first_same_value;
102718334Speter		 classp != 0;
102818334Speter		 classp = classp->next_same_value)
102918334Speter	      if (GET_CODE (classp->exp) == REG
103018334Speter		  && GET_MODE (classp->exp) == GET_MODE (x))
103118334Speter		{
103218334Speter		  make_regs_eqv (regno, REGNO (classp->exp));
103318334Speter		  return 1;
103418334Speter		}
103518334Speter
103618334Speter	  make_new_qty (regno);
103718334Speter	  qty_mode[reg_qty[regno]] = GET_MODE (x);
103818334Speter	  return 1;
103918334Speter	}
104018334Speter
104118334Speter      return 0;
104218334Speter    }
104318334Speter
104418334Speter  /* If X is a SUBREG, we will likely be inserting the inner register in the
104518334Speter     table.  If that register doesn't have an assigned quantity number at
104618334Speter     this point but does later, the insertion that we will be doing now will
104718334Speter     not be accessible because its hash code will have changed.  So assign
104818334Speter     a quantity number now.  */
104918334Speter
105018334Speter  else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG
105118334Speter	   && ! REGNO_QTY_VALID_P (REGNO (SUBREG_REG (x))))
105218334Speter    {
105318334Speter      insert_regs (SUBREG_REG (x), NULL_PTR, 0);
105418334Speter      mention_regs (SUBREG_REG (x));
105518334Speter      return 1;
105618334Speter    }
105718334Speter  else
105818334Speter    return mention_regs (x);
105918334Speter}
106018334Speter
106118334Speter/* Look in or update the hash table.  */
106218334Speter
106318334Speter/* Put the element ELT on the list of free elements.  */
106418334Speter
106518334Speterstatic void
106618334Speterfree_element (elt)
106718334Speter     struct table_elt *elt;
106818334Speter{
106918334Speter  elt->next_same_hash = free_element_chain;
107018334Speter  free_element_chain = elt;
107118334Speter}
107218334Speter
107318334Speter/* Return an element that is free for use.  */
107418334Speter
107518334Speterstatic struct table_elt *
107618334Speterget_element ()
107718334Speter{
107818334Speter  struct table_elt *elt = free_element_chain;
107918334Speter  if (elt)
108018334Speter    {
108118334Speter      free_element_chain = elt->next_same_hash;
108218334Speter      return elt;
108318334Speter    }
108418334Speter  n_elements_made++;
108518334Speter  return (struct table_elt *) oballoc (sizeof (struct table_elt));
108618334Speter}
108718334Speter
108818334Speter/* Remove table element ELT from use in the table.
108918334Speter   HASH is its hash code, made using the HASH macro.
109018334Speter   It's an argument because often that is known in advance
109118334Speter   and we save much time not recomputing it.  */
109218334Speter
109318334Speterstatic void
109418334Speterremove_from_table (elt, hash)
109518334Speter     register struct table_elt *elt;
109618334Speter     unsigned hash;
109718334Speter{
109818334Speter  if (elt == 0)
109918334Speter    return;
110018334Speter
110118334Speter  /* Mark this element as removed.  See cse_insn.  */
110218334Speter  elt->first_same_value = 0;
110318334Speter
110418334Speter  /* Remove the table element from its equivalence class.  */
110518334Speter
110618334Speter  {
110718334Speter    register struct table_elt *prev = elt->prev_same_value;
110818334Speter    register struct table_elt *next = elt->next_same_value;
110918334Speter
111018334Speter    if (next) next->prev_same_value = prev;
111118334Speter
111218334Speter    if (prev)
111318334Speter      prev->next_same_value = next;
111418334Speter    else
111518334Speter      {
111618334Speter	register struct table_elt *newfirst = next;
111718334Speter	while (next)
111818334Speter	  {
111918334Speter	    next->first_same_value = newfirst;
112018334Speter	    next = next->next_same_value;
112118334Speter	  }
112218334Speter      }
112318334Speter  }
112418334Speter
112518334Speter  /* Remove the table element from its hash bucket.  */
112618334Speter
112718334Speter  {
112818334Speter    register struct table_elt *prev = elt->prev_same_hash;
112918334Speter    register struct table_elt *next = elt->next_same_hash;
113018334Speter
113118334Speter    if (next) next->prev_same_hash = prev;
113218334Speter
113318334Speter    if (prev)
113418334Speter      prev->next_same_hash = next;
113518334Speter    else if (table[hash] == elt)
113618334Speter      table[hash] = next;
113718334Speter    else
113818334Speter      {
113918334Speter	/* This entry is not in the proper hash bucket.  This can happen
114018334Speter	   when two classes were merged by `merge_equiv_classes'.  Search
114118334Speter	   for the hash bucket that it heads.  This happens only very
114218334Speter	   rarely, so the cost is acceptable.  */
114318334Speter	for (hash = 0; hash < NBUCKETS; hash++)
114418334Speter	  if (table[hash] == elt)
114518334Speter	    table[hash] = next;
114618334Speter      }
114718334Speter  }
114818334Speter
114918334Speter  /* Remove the table element from its related-value circular chain.  */
115018334Speter
115118334Speter  if (elt->related_value != 0 && elt->related_value != elt)
115218334Speter    {
115318334Speter      register struct table_elt *p = elt->related_value;
115418334Speter      while (p->related_value != elt)
115518334Speter	p = p->related_value;
115618334Speter      p->related_value = elt->related_value;
115718334Speter      if (p->related_value == p)
115818334Speter	p->related_value = 0;
115918334Speter    }
116018334Speter
116118334Speter  free_element (elt);
116218334Speter}
116318334Speter
116418334Speter/* Look up X in the hash table and return its table element,
116518334Speter   or 0 if X is not in the table.
116618334Speter
116718334Speter   MODE is the machine-mode of X, or if X is an integer constant
116818334Speter   with VOIDmode then MODE is the mode with which X will be used.
116918334Speter
117018334Speter   Here we are satisfied to find an expression whose tree structure
117118334Speter   looks like X.  */
117218334Speter
117318334Speterstatic struct table_elt *
117418334Speterlookup (x, hash, mode)
117518334Speter     rtx x;
117618334Speter     unsigned hash;
117718334Speter     enum machine_mode mode;
117818334Speter{
117918334Speter  register struct table_elt *p;
118018334Speter
118118334Speter  for (p = table[hash]; p; p = p->next_same_hash)
118218334Speter    if (mode == p->mode && ((x == p->exp && GET_CODE (x) == REG)
118318334Speter			    || exp_equiv_p (x, p->exp, GET_CODE (x) != REG, 0)))
118418334Speter      return p;
118518334Speter
118618334Speter  return 0;
118718334Speter}
118818334Speter
118918334Speter/* Like `lookup' but don't care whether the table element uses invalid regs.
119018334Speter   Also ignore discrepancies in the machine mode of a register.  */
119118334Speter
119218334Speterstatic struct table_elt *
119318334Speterlookup_for_remove (x, hash, mode)
119418334Speter     rtx x;
119518334Speter     unsigned hash;
119618334Speter     enum machine_mode mode;
119718334Speter{
119818334Speter  register struct table_elt *p;
119918334Speter
120018334Speter  if (GET_CODE (x) == REG)
120118334Speter    {
120218334Speter      int regno = REGNO (x);
120318334Speter      /* Don't check the machine mode when comparing registers;
120418334Speter	 invalidating (REG:SI 0) also invalidates (REG:DF 0).  */
120518334Speter      for (p = table[hash]; p; p = p->next_same_hash)
120618334Speter	if (GET_CODE (p->exp) == REG
120718334Speter	    && REGNO (p->exp) == regno)
120818334Speter	  return p;
120918334Speter    }
121018334Speter  else
121118334Speter    {
121218334Speter      for (p = table[hash]; p; p = p->next_same_hash)
121318334Speter	if (mode == p->mode && (x == p->exp || exp_equiv_p (x, p->exp, 0, 0)))
121418334Speter	  return p;
121518334Speter    }
121618334Speter
121718334Speter  return 0;
121818334Speter}
121918334Speter
122018334Speter/* Look for an expression equivalent to X and with code CODE.
122118334Speter   If one is found, return that expression.  */
122218334Speter
122318334Speterstatic rtx
122418334Speterlookup_as_function (x, code)
122518334Speter     rtx x;
122618334Speter     enum rtx_code code;
122718334Speter{
122818334Speter  register struct table_elt *p = lookup (x, safe_hash (x, VOIDmode) % NBUCKETS,
122918334Speter					 GET_MODE (x));
123018334Speter  if (p == 0)
123118334Speter    return 0;
123218334Speter
123318334Speter  for (p = p->first_same_value; p; p = p->next_same_value)
123418334Speter    {
123518334Speter      if (GET_CODE (p->exp) == code
123618334Speter	  /* Make sure this is a valid entry in the table.  */
123718334Speter	  && exp_equiv_p (p->exp, p->exp, 1, 0))
123818334Speter	return p->exp;
123918334Speter    }
124018334Speter
124118334Speter  return 0;
124218334Speter}
124318334Speter
124418334Speter/* Insert X in the hash table, assuming HASH is its hash code
124518334Speter   and CLASSP is an element of the class it should go in
124618334Speter   (or 0 if a new class should be made).
124718334Speter   It is inserted at the proper position to keep the class in
124818334Speter   the order cheapest first.
124918334Speter
125018334Speter   MODE is the machine-mode of X, or if X is an integer constant
125118334Speter   with VOIDmode then MODE is the mode with which X will be used.
125218334Speter
125318334Speter   For elements of equal cheapness, the most recent one
125418334Speter   goes in front, except that the first element in the list
125518334Speter   remains first unless a cheaper element is added.  The order of
125618334Speter   pseudo-registers does not matter, as canon_reg will be called to
125718334Speter   find the cheapest when a register is retrieved from the table.
125818334Speter
125918334Speter   The in_memory field in the hash table element is set to 0.
126018334Speter   The caller must set it nonzero if appropriate.
126118334Speter
126218334Speter   You should call insert_regs (X, CLASSP, MODIFY) before calling here,
126318334Speter   and if insert_regs returns a nonzero value
126418334Speter   you must then recompute its hash code before calling here.
126518334Speter
126618334Speter   If necessary, update table showing constant values of quantities.  */
126718334Speter
126818334Speter#define CHEAPER(X,Y)   ((X)->cost < (Y)->cost)
126918334Speter
127018334Speterstatic struct table_elt *
127118334Speterinsert (x, classp, hash, mode)
127218334Speter     register rtx x;
127318334Speter     register struct table_elt *classp;
127418334Speter     unsigned hash;
127518334Speter     enum machine_mode mode;
127618334Speter{
127718334Speter  register struct table_elt *elt;
127818334Speter
127918334Speter  /* If X is a register and we haven't made a quantity for it,
128018334Speter     something is wrong.  */
128118334Speter  if (GET_CODE (x) == REG && ! REGNO_QTY_VALID_P (REGNO (x)))
128218334Speter    abort ();
128318334Speter
128418334Speter  /* If X is a hard register, show it is being put in the table.  */
128518334Speter  if (GET_CODE (x) == REG && REGNO (x) < FIRST_PSEUDO_REGISTER)
128618334Speter    {
128718334Speter      int regno = REGNO (x);
128818334Speter      int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
128918334Speter      int i;
129018334Speter
129118334Speter      for (i = regno; i < endregno; i++)
129218334Speter	    SET_HARD_REG_BIT (hard_regs_in_table, i);
129318334Speter    }
129418334Speter
129518334Speter  /* If X is a label, show we recorded it.  */
129618334Speter  if (GET_CODE (x) == LABEL_REF
129718334Speter      || (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS
129818334Speter	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF))
129918334Speter    recorded_label_ref = 1;
130018334Speter
130118334Speter  /* Put an element for X into the right hash bucket.  */
130218334Speter
130318334Speter  elt = get_element ();
130418334Speter  elt->exp = x;
130518334Speter  elt->cost = COST (x);
130618334Speter  elt->next_same_value = 0;
130718334Speter  elt->prev_same_value = 0;
130818334Speter  elt->next_same_hash = table[hash];
130918334Speter  elt->prev_same_hash = 0;
131018334Speter  elt->related_value = 0;
131118334Speter  elt->in_memory = 0;
131218334Speter  elt->mode = mode;
131318334Speter  elt->is_const = (CONSTANT_P (x)
131418334Speter		   /* GNU C++ takes advantage of this for `this'
131518334Speter		      (and other const values).  */
131618334Speter		   || (RTX_UNCHANGING_P (x)
131718334Speter		       && GET_CODE (x) == REG
131818334Speter		       && REGNO (x) >= FIRST_PSEUDO_REGISTER)
131918334Speter		   || FIXED_BASE_PLUS_P (x));
132018334Speter
132118334Speter  if (table[hash])
132218334Speter    table[hash]->prev_same_hash = elt;
132318334Speter  table[hash] = elt;
132418334Speter
132518334Speter  /* Put it into the proper value-class.  */
132618334Speter  if (classp)
132718334Speter    {
132818334Speter      classp = classp->first_same_value;
132918334Speter      if (CHEAPER (elt, classp))
133018334Speter	/* Insert at the head of the class */
133118334Speter	{
133218334Speter	  register struct table_elt *p;
133318334Speter	  elt->next_same_value = classp;
133418334Speter	  classp->prev_same_value = elt;
133518334Speter	  elt->first_same_value = elt;
133618334Speter
133718334Speter	  for (p = classp; p; p = p->next_same_value)
133818334Speter	    p->first_same_value = elt;
133918334Speter	}
134018334Speter      else
134118334Speter	{
134218334Speter	  /* Insert not at head of the class.  */
134318334Speter	  /* Put it after the last element cheaper than X.  */
134418334Speter	  register struct table_elt *p, *next;
134518334Speter	  for (p = classp; (next = p->next_same_value) && CHEAPER (next, elt);
134618334Speter	       p = next);
134718334Speter	  /* Put it after P and before NEXT.  */
134818334Speter	  elt->next_same_value = next;
134918334Speter	  if (next)
135018334Speter	    next->prev_same_value = elt;
135118334Speter	  elt->prev_same_value = p;
135218334Speter	  p->next_same_value = elt;
135318334Speter	  elt->first_same_value = classp;
135418334Speter	}
135518334Speter    }
135618334Speter  else
135718334Speter    elt->first_same_value = elt;
135818334Speter
135918334Speter  /* If this is a constant being set equivalent to a register or a register
136018334Speter     being set equivalent to a constant, note the constant equivalence.
136118334Speter
136218334Speter     If this is a constant, it cannot be equivalent to a different constant,
136318334Speter     and a constant is the only thing that can be cheaper than a register.  So
136418334Speter     we know the register is the head of the class (before the constant was
136518334Speter     inserted).
136618334Speter
136718334Speter     If this is a register that is not already known equivalent to a
136818334Speter     constant, we must check the entire class.
136918334Speter
137018334Speter     If this is a register that is already known equivalent to an insn,
137118334Speter     update `qty_const_insn' to show that `this_insn' is the latest
137218334Speter     insn making that quantity equivalent to the constant.  */
137318334Speter
137418334Speter  if (elt->is_const && classp && GET_CODE (classp->exp) == REG
137518334Speter      && GET_CODE (x) != REG)
137618334Speter    {
137718334Speter      qty_const[reg_qty[REGNO (classp->exp)]]
137818334Speter	= gen_lowpart_if_possible (qty_mode[reg_qty[REGNO (classp->exp)]], x);
137918334Speter      qty_const_insn[reg_qty[REGNO (classp->exp)]] = this_insn;
138018334Speter    }
138118334Speter
138218334Speter  else if (GET_CODE (x) == REG && classp && ! qty_const[reg_qty[REGNO (x)]]
138318334Speter	   && ! elt->is_const)
138418334Speter    {
138518334Speter      register struct table_elt *p;
138618334Speter
138718334Speter      for (p = classp; p != 0; p = p->next_same_value)
138818334Speter	{
138918334Speter	  if (p->is_const && GET_CODE (p->exp) != REG)
139018334Speter	    {
139118334Speter	      qty_const[reg_qty[REGNO (x)]]
139218334Speter		= gen_lowpart_if_possible (GET_MODE (x), p->exp);
139318334Speter	      qty_const_insn[reg_qty[REGNO (x)]] = this_insn;
139418334Speter	      break;
139518334Speter	    }
139618334Speter	}
139718334Speter    }
139818334Speter
139918334Speter  else if (GET_CODE (x) == REG && qty_const[reg_qty[REGNO (x)]]
140018334Speter	   && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]])
140118334Speter    qty_const_insn[reg_qty[REGNO (x)]] = this_insn;
140218334Speter
140318334Speter  /* If this is a constant with symbolic value,
140418334Speter     and it has a term with an explicit integer value,
140518334Speter     link it up with related expressions.  */
140618334Speter  if (GET_CODE (x) == CONST)
140718334Speter    {
140818334Speter      rtx subexp = get_related_value (x);
140918334Speter      unsigned subhash;
141018334Speter      struct table_elt *subelt, *subelt_prev;
141118334Speter
141218334Speter      if (subexp != 0)
141318334Speter	{
141418334Speter	  /* Get the integer-free subexpression in the hash table.  */
141518334Speter	  subhash = safe_hash (subexp, mode) % NBUCKETS;
141618334Speter	  subelt = lookup (subexp, subhash, mode);
141718334Speter	  if (subelt == 0)
141818334Speter	    subelt = insert (subexp, NULL_PTR, subhash, mode);
141918334Speter	  /* Initialize SUBELT's circular chain if it has none.  */
142018334Speter	  if (subelt->related_value == 0)
142118334Speter	    subelt->related_value = subelt;
142218334Speter	  /* Find the element in the circular chain that precedes SUBELT.  */
142318334Speter	  subelt_prev = subelt;
142418334Speter	  while (subelt_prev->related_value != subelt)
142518334Speter	    subelt_prev = subelt_prev->related_value;
142618334Speter	  /* Put new ELT into SUBELT's circular chain just before SUBELT.
142718334Speter	     This way the element that follows SUBELT is the oldest one.  */
142818334Speter	  elt->related_value = subelt_prev->related_value;
142918334Speter	  subelt_prev->related_value = elt;
143018334Speter	}
143118334Speter    }
143218334Speter
143318334Speter  return elt;
143418334Speter}
143518334Speter
143618334Speter/* Given two equivalence classes, CLASS1 and CLASS2, put all the entries from
143718334Speter   CLASS2 into CLASS1.  This is done when we have reached an insn which makes
143818334Speter   the two classes equivalent.
143918334Speter
144018334Speter   CLASS1 will be the surviving class; CLASS2 should not be used after this
144118334Speter   call.
144218334Speter
144318334Speter   Any invalid entries in CLASS2 will not be copied.  */
144418334Speter
144518334Speterstatic void
144618334Spetermerge_equiv_classes (class1, class2)
144718334Speter     struct table_elt *class1, *class2;
144818334Speter{
144918334Speter  struct table_elt *elt, *next, *new;
145018334Speter
145118334Speter  /* Ensure we start with the head of the classes.  */
145218334Speter  class1 = class1->first_same_value;
145318334Speter  class2 = class2->first_same_value;
145418334Speter
145518334Speter  /* If they were already equal, forget it.  */
145618334Speter  if (class1 == class2)
145718334Speter    return;
145818334Speter
145918334Speter  for (elt = class2; elt; elt = next)
146018334Speter    {
146118334Speter      unsigned hash;
146218334Speter      rtx exp = elt->exp;
146318334Speter      enum machine_mode mode = elt->mode;
146418334Speter
146518334Speter      next = elt->next_same_value;
146618334Speter
146718334Speter      /* Remove old entry, make a new one in CLASS1's class.
146818334Speter	 Don't do this for invalid entries as we cannot find their
146918334Speter	 hash code (it also isn't necessary). */
147018334Speter      if (GET_CODE (exp) == REG || exp_equiv_p (exp, exp, 1, 0))
147118334Speter	{
147218334Speter	  hash_arg_in_memory = 0;
147318334Speter	  hash_arg_in_struct = 0;
147418334Speter	  hash = HASH (exp, mode);
147518334Speter
147618334Speter	  if (GET_CODE (exp) == REG)
147718334Speter	    delete_reg_equiv (REGNO (exp));
147818334Speter
147918334Speter	  remove_from_table (elt, hash);
148018334Speter
148118334Speter	  if (insert_regs (exp, class1, 0))
148218334Speter	    {
148318334Speter	      rehash_using_reg (exp);
148418334Speter	      hash = HASH (exp, mode);
148518334Speter	    }
148618334Speter	  new = insert (exp, class1, hash, mode);
148718334Speter	  new->in_memory = hash_arg_in_memory;
148818334Speter	  new->in_struct = hash_arg_in_struct;
148918334Speter	}
149018334Speter    }
149118334Speter}
149218334Speter
149318334Speter/* Remove from the hash table, or mark as invalid,
149418334Speter   all expressions whose values could be altered by storing in X.
149518334Speter   X is a register, a subreg, or a memory reference with nonvarying address
149618334Speter   (because, when a memory reference with a varying address is stored in,
149718334Speter   all memory references are removed by invalidate_memory
149818334Speter   so specific invalidation is superfluous).
149918334Speter   FULL_MODE, if not VOIDmode, indicates that this much should be invalidated
150018334Speter   instead of just the amount indicated by the mode of X.  This is only used
150118334Speter   for bitfield stores into memory.
150218334Speter
150318334Speter   A nonvarying address may be just a register or just
150418334Speter   a symbol reference, or it may be either of those plus
150518334Speter   a numeric offset.  */
150618334Speter
150718334Speterstatic void
150818334Speterinvalidate (x, full_mode)
150918334Speter     rtx x;
151018334Speter     enum machine_mode full_mode;
151118334Speter{
151218334Speter  register int i;
151318334Speter  register struct table_elt *p;
151418334Speter  rtx base;
151518334Speter  HOST_WIDE_INT start, end;
151618334Speter
151718334Speter  /* If X is a register, dependencies on its contents
151818334Speter     are recorded through the qty number mechanism.
151918334Speter     Just change the qty number of the register,
152018334Speter     mark it as invalid for expressions that refer to it,
152118334Speter     and remove it itself.  */
152218334Speter
152318334Speter  if (GET_CODE (x) == REG)
152418334Speter    {
152518334Speter      register int regno = REGNO (x);
152618334Speter      register unsigned hash = HASH (x, GET_MODE (x));
152718334Speter
152818334Speter      /* Remove REGNO from any quantity list it might be on and indicate
152918334Speter	 that it's value might have changed.  If it is a pseudo, remove its
153018334Speter	 entry from the hash table.
153118334Speter
153218334Speter	 For a hard register, we do the first two actions above for any
153318334Speter	 additional hard registers corresponding to X.  Then, if any of these
153418334Speter	 registers are in the table, we must remove any REG entries that
153518334Speter	 overlap these registers.  */
153618334Speter
153718334Speter      delete_reg_equiv (regno);
153818334Speter      reg_tick[regno]++;
153918334Speter
154018334Speter      if (regno >= FIRST_PSEUDO_REGISTER)
154118334Speter	{
154218334Speter	  /* Because a register can be referenced in more than one mode,
154318334Speter	     we might have to remove more than one table entry.  */
154418334Speter
154518334Speter	  struct table_elt *elt;
154618334Speter
154718334Speter	  while (elt = lookup_for_remove (x, hash, GET_MODE (x)))
154818334Speter	    remove_from_table (elt, hash);
154918334Speter	}
155018334Speter      else
155118334Speter	{
155218334Speter	  HOST_WIDE_INT in_table
155318334Speter	    = TEST_HARD_REG_BIT (hard_regs_in_table, regno);
155418334Speter	  int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
155518334Speter	  int tregno, tendregno;
155618334Speter	  register struct table_elt *p, *next;
155718334Speter
155818334Speter	  CLEAR_HARD_REG_BIT (hard_regs_in_table, regno);
155918334Speter
156018334Speter	  for (i = regno + 1; i < endregno; i++)
156118334Speter	    {
156218334Speter	      in_table |= TEST_HARD_REG_BIT (hard_regs_in_table, i);
156318334Speter	      CLEAR_HARD_REG_BIT (hard_regs_in_table, i);
156418334Speter	      delete_reg_equiv (i);
156518334Speter	      reg_tick[i]++;
156618334Speter	    }
156718334Speter
156818334Speter	  if (in_table)
156918334Speter	    for (hash = 0; hash < NBUCKETS; hash++)
157018334Speter	      for (p = table[hash]; p; p = next)
157118334Speter		{
157218334Speter		  next = p->next_same_hash;
157318334Speter
157418334Speter		  if (GET_CODE (p->exp) != REG
157518334Speter		      || REGNO (p->exp) >= FIRST_PSEUDO_REGISTER)
157618334Speter		    continue;
157718334Speter
157818334Speter		  tregno = REGNO (p->exp);
157918334Speter		  tendregno
158018334Speter		    = tregno + HARD_REGNO_NREGS (tregno, GET_MODE (p->exp));
158118334Speter		  if (tendregno > regno && tregno < endregno)
158218334Speter		  remove_from_table (p, hash);
158318334Speter		}
158418334Speter	}
158518334Speter
158618334Speter      return;
158718334Speter    }
158818334Speter
158918334Speter  if (GET_CODE (x) == SUBREG)
159018334Speter    {
159118334Speter      if (GET_CODE (SUBREG_REG (x)) != REG)
159218334Speter	abort ();
159318334Speter      invalidate (SUBREG_REG (x), VOIDmode);
159418334Speter      return;
159518334Speter    }
159618334Speter
159718334Speter  /* X is not a register; it must be a memory reference with
159818334Speter     a nonvarying address.  Remove all hash table elements
159918334Speter     that refer to overlapping pieces of memory.  */
160018334Speter
160118334Speter  if (GET_CODE (x) != MEM)
160218334Speter    abort ();
160318334Speter
160418334Speter  if (full_mode == VOIDmode)
160518334Speter    full_mode = GET_MODE (x);
160618334Speter
160718334Speter  set_nonvarying_address_components (XEXP (x, 0), GET_MODE_SIZE (full_mode),
160818334Speter				     &base, &start, &end);
160918334Speter
161018334Speter  for (i = 0; i < NBUCKETS; i++)
161118334Speter    {
161218334Speter      register struct table_elt *next;
161318334Speter      for (p = table[i]; p; p = next)
161418334Speter	{
161518334Speter	  next = p->next_same_hash;
161618334Speter	  if (refers_to_mem_p (p->exp, base, start, end))
161718334Speter	    remove_from_table (p, i);
161818334Speter	}
161918334Speter    }
162018334Speter}
162118334Speter
162218334Speter/* Remove all expressions that refer to register REGNO,
162318334Speter   since they are already invalid, and we are about to
162418334Speter   mark that register valid again and don't want the old
162518334Speter   expressions to reappear as valid.  */
162618334Speter
162718334Speterstatic void
162818334Speterremove_invalid_refs (regno)
162918334Speter     int regno;
163018334Speter{
163118334Speter  register int i;
163218334Speter  register struct table_elt *p, *next;
163318334Speter
163418334Speter  for (i = 0; i < NBUCKETS; i++)
163518334Speter    for (p = table[i]; p; p = next)
163618334Speter      {
163718334Speter	next = p->next_same_hash;
163818334Speter	if (GET_CODE (p->exp) != REG
163918334Speter	    && refers_to_regno_p (regno, regno + 1, p->exp, NULL_PTR))
164018334Speter	  remove_from_table (p, i);
164118334Speter      }
164218334Speter}
164318334Speter
164418334Speter/* Recompute the hash codes of any valid entries in the hash table that
164518334Speter   reference X, if X is a register, or SUBREG_REG (X) if X is a SUBREG.
164618334Speter
164718334Speter   This is called when we make a jump equivalence.  */
164818334Speter
164918334Speterstatic void
165018334Speterrehash_using_reg (x)
165118334Speter     rtx x;
165218334Speter{
165318334Speter  int i;
165418334Speter  struct table_elt *p, *next;
165518334Speter  unsigned hash;
165618334Speter
165718334Speter  if (GET_CODE (x) == SUBREG)
165818334Speter    x = SUBREG_REG (x);
165918334Speter
166018334Speter  /* If X is not a register or if the register is known not to be in any
166118334Speter     valid entries in the table, we have no work to do.  */
166218334Speter
166318334Speter  if (GET_CODE (x) != REG
166418334Speter      || reg_in_table[REGNO (x)] < 0
166518334Speter      || reg_in_table[REGNO (x)] != reg_tick[REGNO (x)])
166618334Speter    return;
166718334Speter
166818334Speter  /* Scan all hash chains looking for valid entries that mention X.
166918334Speter     If we find one and it is in the wrong hash chain, move it.  We can skip
167018334Speter     objects that are registers, since they are handled specially.  */
167118334Speter
167218334Speter  for (i = 0; i < NBUCKETS; i++)
167318334Speter    for (p = table[i]; p; p = next)
167418334Speter      {
167518334Speter	next = p->next_same_hash;
167618334Speter	if (GET_CODE (p->exp) != REG && reg_mentioned_p (x, p->exp)
167718334Speter	    && exp_equiv_p (p->exp, p->exp, 1, 0)
167818334Speter	    && i != (hash = safe_hash (p->exp, p->mode) % NBUCKETS))
167918334Speter	  {
168018334Speter	    if (p->next_same_hash)
168118334Speter	      p->next_same_hash->prev_same_hash = p->prev_same_hash;
168218334Speter
168318334Speter	    if (p->prev_same_hash)
168418334Speter	      p->prev_same_hash->next_same_hash = p->next_same_hash;
168518334Speter	    else
168618334Speter	      table[i] = p->next_same_hash;
168718334Speter
168818334Speter	    p->next_same_hash = table[hash];
168918334Speter	    p->prev_same_hash = 0;
169018334Speter	    if (table[hash])
169118334Speter	      table[hash]->prev_same_hash = p;
169218334Speter	    table[hash] = p;
169318334Speter	  }
169418334Speter      }
169518334Speter}
169618334Speter
169718334Speter/* Remove from the hash table all expressions that reference memory,
169818334Speter   or some of them as specified by *WRITES.  */
169918334Speter
170018334Speterstatic void
170118334Speterinvalidate_memory (writes)
170218334Speter     struct write_data *writes;
170318334Speter{
170418334Speter  register int i;
170518334Speter  register struct table_elt *p, *next;
170618334Speter  int all = writes->all;
170718334Speter  int nonscalar = writes->nonscalar;
170818334Speter
170918334Speter  for (i = 0; i < NBUCKETS; i++)
171018334Speter    for (p = table[i]; p; p = next)
171118334Speter      {
171218334Speter	next = p->next_same_hash;
171318334Speter	if (p->in_memory
171418334Speter	    && (all
171518334Speter		|| (nonscalar && p->in_struct)
171618334Speter		|| cse_rtx_addr_varies_p (p->exp)))
171718334Speter	  remove_from_table (p, i);
171818334Speter      }
171918334Speter}
172018334Speter
172118334Speter/* Remove from the hash table any expression that is a call-clobbered
172218334Speter   register.  Also update their TICK values.  */
172318334Speter
172418334Speterstatic void
172518334Speterinvalidate_for_call ()
172618334Speter{
172718334Speter  int regno, endregno;
172818334Speter  int i;
172918334Speter  unsigned hash;
173018334Speter  struct table_elt *p, *next;
173118334Speter  int in_table = 0;
173218334Speter
173318334Speter  /* Go through all the hard registers.  For each that is clobbered in
173418334Speter     a CALL_INSN, remove the register from quantity chains and update
173518334Speter     reg_tick if defined.  Also see if any of these registers is currently
173618334Speter     in the table.  */
173718334Speter
173818334Speter  for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
173918334Speter    if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno))
174018334Speter      {
174118334Speter	delete_reg_equiv (regno);
174218334Speter	if (reg_tick[regno] >= 0)
174318334Speter	  reg_tick[regno]++;
174418334Speter
174518334Speter	in_table |= (TEST_HARD_REG_BIT (hard_regs_in_table, regno) != 0);
174618334Speter      }
174718334Speter
174818334Speter  /* In the case where we have no call-clobbered hard registers in the
174918334Speter     table, we are done.  Otherwise, scan the table and remove any
175018334Speter     entry that overlaps a call-clobbered register.  */
175118334Speter
175218334Speter  if (in_table)
175318334Speter    for (hash = 0; hash < NBUCKETS; hash++)
175418334Speter      for (p = table[hash]; p; p = next)
175518334Speter	{
175618334Speter	  next = p->next_same_hash;
175718334Speter
175818334Speter	  if (GET_CODE (p->exp) != REG
175918334Speter	      || REGNO (p->exp) >= FIRST_PSEUDO_REGISTER)
176018334Speter	    continue;
176118334Speter
176218334Speter	  regno = REGNO (p->exp);
176318334Speter	  endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (p->exp));
176418334Speter
176518334Speter	  for (i = regno; i < endregno; i++)
176618334Speter	    if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
176718334Speter	      {
176818334Speter		remove_from_table (p, hash);
176918334Speter		break;
177018334Speter	      }
177118334Speter	}
177218334Speter}
177318334Speter
177418334Speter/* Given an expression X of type CONST,
177518334Speter   and ELT which is its table entry (or 0 if it
177618334Speter   is not in the hash table),
177718334Speter   return an alternate expression for X as a register plus integer.
177818334Speter   If none can be found, return 0.  */
177918334Speter
178018334Speterstatic rtx
178118334Speteruse_related_value (x, elt)
178218334Speter     rtx x;
178318334Speter     struct table_elt *elt;
178418334Speter{
178518334Speter  register struct table_elt *relt = 0;
178618334Speter  register struct table_elt *p, *q;
178718334Speter  HOST_WIDE_INT offset;
178818334Speter
178918334Speter  /* First, is there anything related known?
179018334Speter     If we have a table element, we can tell from that.
179118334Speter     Otherwise, must look it up.  */
179218334Speter
179318334Speter  if (elt != 0 && elt->related_value != 0)
179418334Speter    relt = elt;
179518334Speter  else if (elt == 0 && GET_CODE (x) == CONST)
179618334Speter    {
179718334Speter      rtx subexp = get_related_value (x);
179818334Speter      if (subexp != 0)
179918334Speter	relt = lookup (subexp,
180018334Speter		       safe_hash (subexp, GET_MODE (subexp)) % NBUCKETS,
180118334Speter		       GET_MODE (subexp));
180218334Speter    }
180318334Speter
180418334Speter  if (relt == 0)
180518334Speter    return 0;
180618334Speter
180718334Speter  /* Search all related table entries for one that has an
180818334Speter     equivalent register.  */
180918334Speter
181018334Speter  p = relt;
181118334Speter  while (1)
181218334Speter    {
181318334Speter      /* This loop is strange in that it is executed in two different cases.
181418334Speter	 The first is when X is already in the table.  Then it is searching
181518334Speter	 the RELATED_VALUE list of X's class (RELT).  The second case is when
181618334Speter	 X is not in the table.  Then RELT points to a class for the related
181718334Speter	 value.
181818334Speter
181918334Speter	 Ensure that, whatever case we are in, that we ignore classes that have
182018334Speter	 the same value as X.  */
182118334Speter
182218334Speter      if (rtx_equal_p (x, p->exp))
182318334Speter	q = 0;
182418334Speter      else
182518334Speter	for (q = p->first_same_value; q; q = q->next_same_value)
182618334Speter	  if (GET_CODE (q->exp) == REG)
182718334Speter	    break;
182818334Speter
182918334Speter      if (q)
183018334Speter	break;
183118334Speter
183218334Speter      p = p->related_value;
183318334Speter
183418334Speter      /* We went all the way around, so there is nothing to be found.
183518334Speter	 Alternatively, perhaps RELT was in the table for some other reason
183618334Speter	 and it has no related values recorded.  */
183718334Speter      if (p == relt || p == 0)
183818334Speter	break;
183918334Speter    }
184018334Speter
184118334Speter  if (q == 0)
184218334Speter    return 0;
184318334Speter
184418334Speter  offset = (get_integer_term (x) - get_integer_term (p->exp));
184518334Speter  /* Note: OFFSET may be 0 if P->xexp and X are related by commutativity.  */
184618334Speter  return plus_constant (q->exp, offset);
184718334Speter}
184818334Speter
184918334Speter/* Hash an rtx.  We are careful to make sure the value is never negative.
185018334Speter   Equivalent registers hash identically.
185118334Speter   MODE is used in hashing for CONST_INTs only;
185218334Speter   otherwise the mode of X is used.
185318334Speter
185418334Speter   Store 1 in do_not_record if any subexpression is volatile.
185518334Speter
185618334Speter   Store 1 in hash_arg_in_memory if X contains a MEM rtx
185718334Speter   which does not have the RTX_UNCHANGING_P bit set.
185818334Speter   In this case, also store 1 in hash_arg_in_struct
185918334Speter   if there is a MEM rtx which has the MEM_IN_STRUCT_P bit set.
186018334Speter
186118334Speter   Note that cse_insn knows that the hash code of a MEM expression
186218334Speter   is just (int) MEM plus the hash code of the address.  */
186318334Speter
186418334Speterstatic unsigned
186518334Spetercanon_hash (x, mode)
186618334Speter     rtx x;
186718334Speter     enum machine_mode mode;
186818334Speter{
186918334Speter  register int i, j;
187018334Speter  register unsigned hash = 0;
187118334Speter  register enum rtx_code code;
187218334Speter  register char *fmt;
187318334Speter
187418334Speter  /* repeat is used to turn tail-recursion into iteration.  */
187518334Speter repeat:
187618334Speter  if (x == 0)
187718334Speter    return hash;
187818334Speter
187918334Speter  code = GET_CODE (x);
188018334Speter  switch (code)
188118334Speter    {
188218334Speter    case REG:
188318334Speter      {
188418334Speter	register int regno = REGNO (x);
188518334Speter
188618334Speter	/* On some machines, we can't record any non-fixed hard register,
188718334Speter	   because extending its life will cause reload problems.  We
188818334Speter	   consider ap, fp, and sp to be fixed for this purpose.
188918334Speter	   On all machines, we can't record any global registers. */
189018334Speter
189118334Speter	if (regno < FIRST_PSEUDO_REGISTER
189218334Speter	    && (global_regs[regno]
189318334Speter#ifdef SMALL_REGISTER_CLASSES
189418334Speter		|| (! fixed_regs[regno]
189518334Speter		    && regno != FRAME_POINTER_REGNUM
189618334Speter		    && regno != HARD_FRAME_POINTER_REGNUM
189718334Speter		    && regno != ARG_POINTER_REGNUM
189818334Speter		    && regno != STACK_POINTER_REGNUM)
189918334Speter#endif
190018334Speter		))
190118334Speter	  {
190218334Speter	    do_not_record = 1;
190318334Speter	    return 0;
190418334Speter	  }
190518334Speter	hash += ((unsigned) REG << 7) + (unsigned) reg_qty[regno];
190618334Speter	return hash;
190718334Speter      }
190818334Speter
190918334Speter    case CONST_INT:
191018334Speter      {
191118334Speter	unsigned HOST_WIDE_INT tem = INTVAL (x);
191218334Speter	hash += ((unsigned) CONST_INT << 7) + (unsigned) mode + tem;
191318334Speter	return hash;
191418334Speter      }
191518334Speter
191618334Speter    case CONST_DOUBLE:
191718334Speter      /* This is like the general case, except that it only counts
191818334Speter	 the integers representing the constant.  */
191918334Speter      hash += (unsigned) code + (unsigned) GET_MODE (x);
192018334Speter      if (GET_MODE (x) != VOIDmode)
192118334Speter	for (i = 2; i < GET_RTX_LENGTH (CONST_DOUBLE); i++)
192218334Speter	  {
192318334Speter	    unsigned tem = XINT (x, i);
192418334Speter	    hash += tem;
192518334Speter	  }
192618334Speter      else
192718334Speter	hash += ((unsigned) CONST_DOUBLE_LOW (x)
192818334Speter		 + (unsigned) CONST_DOUBLE_HIGH (x));
192918334Speter      return hash;
193018334Speter
193118334Speter      /* Assume there is only one rtx object for any given label.  */
193218334Speter    case LABEL_REF:
193318334Speter      hash
193418334Speter	+= ((unsigned) LABEL_REF << 7) + (unsigned HOST_WIDE_INT) XEXP (x, 0);
193518334Speter      return hash;
193618334Speter
193718334Speter    case SYMBOL_REF:
193818334Speter      hash
193918334Speter	+= ((unsigned) SYMBOL_REF << 7) + (unsigned HOST_WIDE_INT) XSTR (x, 0);
194018334Speter      return hash;
194118334Speter
194218334Speter    case MEM:
194318334Speter      if (MEM_VOLATILE_P (x))
194418334Speter	{
194518334Speter	  do_not_record = 1;
194618334Speter	  return 0;
194718334Speter	}
194818334Speter      if (! RTX_UNCHANGING_P (x))
194918334Speter	{
195018334Speter	  hash_arg_in_memory = 1;
195118334Speter	  if (MEM_IN_STRUCT_P (x)) hash_arg_in_struct = 1;
195218334Speter	}
195318334Speter      /* Now that we have already found this special case,
195418334Speter	 might as well speed it up as much as possible.  */
195518334Speter      hash += (unsigned) MEM;
195618334Speter      x = XEXP (x, 0);
195718334Speter      goto repeat;
195818334Speter
195918334Speter    case PRE_DEC:
196018334Speter    case PRE_INC:
196118334Speter    case POST_DEC:
196218334Speter    case POST_INC:
196318334Speter    case PC:
196418334Speter    case CC0:
196518334Speter    case CALL:
196618334Speter    case UNSPEC_VOLATILE:
196718334Speter      do_not_record = 1;
196818334Speter      return 0;
196918334Speter
197018334Speter    case ASM_OPERANDS:
197118334Speter      if (MEM_VOLATILE_P (x))
197218334Speter	{
197318334Speter	  do_not_record = 1;
197418334Speter	  return 0;
197518334Speter	}
197618334Speter    }
197718334Speter
197818334Speter  i = GET_RTX_LENGTH (code) - 1;
197918334Speter  hash += (unsigned) code + (unsigned) GET_MODE (x);
198018334Speter  fmt = GET_RTX_FORMAT (code);
198118334Speter  for (; i >= 0; i--)
198218334Speter    {
198318334Speter      if (fmt[i] == 'e')
198418334Speter	{
198518334Speter	  rtx tem = XEXP (x, i);
198618334Speter
198718334Speter	  /* If we are about to do the last recursive call
198818334Speter	     needed at this level, change it into iteration.
198918334Speter	     This function  is called enough to be worth it.  */
199018334Speter	  if (i == 0)
199118334Speter	    {
199218334Speter	      x = tem;
199318334Speter	      goto repeat;
199418334Speter	    }
199518334Speter	  hash += canon_hash (tem, 0);
199618334Speter	}
199718334Speter      else if (fmt[i] == 'E')
199818334Speter	for (j = 0; j < XVECLEN (x, i); j++)
199918334Speter	  hash += canon_hash (XVECEXP (x, i, j), 0);
200018334Speter      else if (fmt[i] == 's')
200118334Speter	{
200218334Speter	  register unsigned char *p = (unsigned char *) XSTR (x, i);
200318334Speter	  if (p)
200418334Speter	    while (*p)
200518334Speter	      hash += *p++;
200618334Speter	}
200718334Speter      else if (fmt[i] == 'i')
200818334Speter	{
200918334Speter	  register unsigned tem = XINT (x, i);
201018334Speter	  hash += tem;
201118334Speter	}
201218334Speter      else
201318334Speter	abort ();
201418334Speter    }
201518334Speter  return hash;
201618334Speter}
201718334Speter
201818334Speter/* Like canon_hash but with no side effects.  */
201918334Speter
202018334Speterstatic unsigned
202118334Spetersafe_hash (x, mode)
202218334Speter     rtx x;
202318334Speter     enum machine_mode mode;
202418334Speter{
202518334Speter  int save_do_not_record = do_not_record;
202618334Speter  int save_hash_arg_in_memory = hash_arg_in_memory;
202718334Speter  int save_hash_arg_in_struct = hash_arg_in_struct;
202818334Speter  unsigned hash = canon_hash (x, mode);
202918334Speter  hash_arg_in_memory = save_hash_arg_in_memory;
203018334Speter  hash_arg_in_struct = save_hash_arg_in_struct;
203118334Speter  do_not_record = save_do_not_record;
203218334Speter  return hash;
203318334Speter}
203418334Speter
203518334Speter/* Return 1 iff X and Y would canonicalize into the same thing,
203618334Speter   without actually constructing the canonicalization of either one.
203718334Speter   If VALIDATE is nonzero,
203818334Speter   we assume X is an expression being processed from the rtl
203918334Speter   and Y was found in the hash table.  We check register refs
204018334Speter   in Y for being marked as valid.
204118334Speter
204218334Speter   If EQUAL_VALUES is nonzero, we allow a register to match a constant value
204318334Speter   that is known to be in the register.  Ordinarily, we don't allow them
204418334Speter   to match, because letting them match would cause unpredictable results
204518334Speter   in all the places that search a hash table chain for an equivalent
204618334Speter   for a given value.  A possible equivalent that has different structure
204718334Speter   has its hash code computed from different data.  Whether the hash code
204818334Speter   is the same as that of the the given value is pure luck.  */
204918334Speter
205018334Speterstatic int
205118334Speterexp_equiv_p (x, y, validate, equal_values)
205218334Speter     rtx x, y;
205318334Speter     int validate;
205418334Speter     int equal_values;
205518334Speter{
205618334Speter  register int i, j;
205718334Speter  register enum rtx_code code;
205818334Speter  register char *fmt;
205918334Speter
206018334Speter  /* Note: it is incorrect to assume an expression is equivalent to itself
206118334Speter     if VALIDATE is nonzero.  */
206218334Speter  if (x == y && !validate)
206318334Speter    return 1;
206418334Speter  if (x == 0 || y == 0)
206518334Speter    return x == y;
206618334Speter
206718334Speter  code = GET_CODE (x);
206818334Speter  if (code != GET_CODE (y))
206918334Speter    {
207018334Speter      if (!equal_values)
207118334Speter	return 0;
207218334Speter
207318334Speter      /* If X is a constant and Y is a register or vice versa, they may be
207418334Speter	 equivalent.  We only have to validate if Y is a register.  */
207518334Speter      if (CONSTANT_P (x) && GET_CODE (y) == REG
207618334Speter	  && REGNO_QTY_VALID_P (REGNO (y))
207718334Speter	  && GET_MODE (y) == qty_mode[reg_qty[REGNO (y)]]
207818334Speter	  && rtx_equal_p (x, qty_const[reg_qty[REGNO (y)]])
207918334Speter	  && (! validate || reg_in_table[REGNO (y)] == reg_tick[REGNO (y)]))
208018334Speter	return 1;
208118334Speter
208218334Speter      if (CONSTANT_P (y) && code == REG
208318334Speter	  && REGNO_QTY_VALID_P (REGNO (x))
208418334Speter	  && GET_MODE (x) == qty_mode[reg_qty[REGNO (x)]]
208518334Speter	  && rtx_equal_p (y, qty_const[reg_qty[REGNO (x)]]))
208618334Speter	return 1;
208718334Speter
208818334Speter      return 0;
208918334Speter    }
209018334Speter
209118334Speter  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.  */
209218334Speter  if (GET_MODE (x) != GET_MODE (y))
209318334Speter    return 0;
209418334Speter
209518334Speter  switch (code)
209618334Speter    {
209718334Speter    case PC:
209818334Speter    case CC0:
209918334Speter      return x == y;
210018334Speter
210118334Speter    case CONST_INT:
210218334Speter      return INTVAL (x) == INTVAL (y);
210318334Speter
210418334Speter    case LABEL_REF:
210518334Speter      return XEXP (x, 0) == XEXP (y, 0);
210618334Speter
210718334Speter    case SYMBOL_REF:
210818334Speter      return XSTR (x, 0) == XSTR (y, 0);
210918334Speter
211018334Speter    case REG:
211118334Speter      {
211218334Speter	int regno = REGNO (y);
211318334Speter	int endregno
211418334Speter	  = regno + (regno >= FIRST_PSEUDO_REGISTER ? 1
211518334Speter		     : HARD_REGNO_NREGS (regno, GET_MODE (y)));
211618334Speter	int i;
211718334Speter
211818334Speter	/* If the quantities are not the same, the expressions are not
211918334Speter	   equivalent.  If there are and we are not to validate, they
212018334Speter	   are equivalent.  Otherwise, ensure all regs are up-to-date.  */
212118334Speter
212218334Speter	if (reg_qty[REGNO (x)] != reg_qty[regno])
212318334Speter	  return 0;
212418334Speter
212518334Speter	if (! validate)
212618334Speter	  return 1;
212718334Speter
212818334Speter	for (i = regno; i < endregno; i++)
212918334Speter	  if (reg_in_table[i] != reg_tick[i])
213018334Speter	    return 0;
213118334Speter
213218334Speter	return 1;
213318334Speter      }
213418334Speter
213518334Speter    /*  For commutative operations, check both orders.  */
213618334Speter    case PLUS:
213718334Speter    case MULT:
213818334Speter    case AND:
213918334Speter    case IOR:
214018334Speter    case XOR:
214118334Speter    case NE:
214218334Speter    case EQ:
214318334Speter      return ((exp_equiv_p (XEXP (x, 0), XEXP (y, 0), validate, equal_values)
214418334Speter	       && exp_equiv_p (XEXP (x, 1), XEXP (y, 1),
214518334Speter			       validate, equal_values))
214618334Speter	      || (exp_equiv_p (XEXP (x, 0), XEXP (y, 1),
214718334Speter			       validate, equal_values)
214818334Speter		  && exp_equiv_p (XEXP (x, 1), XEXP (y, 0),
214918334Speter				  validate, equal_values)));
215018334Speter    }
215118334Speter
215218334Speter  /* Compare the elements.  If any pair of corresponding elements
215318334Speter     fail to match, return 0 for the whole things.  */
215418334Speter
215518334Speter  fmt = GET_RTX_FORMAT (code);
215618334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
215718334Speter    {
215818334Speter      switch (fmt[i])
215918334Speter	{
216018334Speter	case 'e':
216118334Speter	  if (! exp_equiv_p (XEXP (x, i), XEXP (y, i), validate, equal_values))
216218334Speter	    return 0;
216318334Speter	  break;
216418334Speter
216518334Speter	case 'E':
216618334Speter	  if (XVECLEN (x, i) != XVECLEN (y, i))
216718334Speter	    return 0;
216818334Speter	  for (j = 0; j < XVECLEN (x, i); j++)
216918334Speter	    if (! exp_equiv_p (XVECEXP (x, i, j), XVECEXP (y, i, j),
217018334Speter			       validate, equal_values))
217118334Speter	      return 0;
217218334Speter	  break;
217318334Speter
217418334Speter	case 's':
217518334Speter	  if (strcmp (XSTR (x, i), XSTR (y, i)))
217618334Speter	    return 0;
217718334Speter	  break;
217818334Speter
217918334Speter	case 'i':
218018334Speter	  if (XINT (x, i) != XINT (y, i))
218118334Speter	    return 0;
218218334Speter	  break;
218318334Speter
218418334Speter	case 'w':
218518334Speter	  if (XWINT (x, i) != XWINT (y, i))
218618334Speter	    return 0;
218718334Speter	break;
218818334Speter
218918334Speter	case '0':
219018334Speter	  break;
219118334Speter
219218334Speter	default:
219318334Speter	  abort ();
219418334Speter	}
219518334Speter      }
219618334Speter
219718334Speter  return 1;
219818334Speter}
219918334Speter
220018334Speter/* Return 1 iff any subexpression of X matches Y.
220118334Speter   Here we do not require that X or Y be valid (for registers referred to)
220218334Speter   for being in the hash table.  */
220318334Speter
220418334Speterstatic int
220518334Speterrefers_to_p (x, y)
220618334Speter     rtx x, y;
220718334Speter{
220818334Speter  register int i;
220918334Speter  register enum rtx_code code;
221018334Speter  register char *fmt;
221118334Speter
221218334Speter repeat:
221318334Speter  if (x == y)
221418334Speter    return 1;
221518334Speter  if (x == 0 || y == 0)
221618334Speter    return 0;
221718334Speter
221818334Speter  code = GET_CODE (x);
221918334Speter  /* If X as a whole has the same code as Y, they may match.
222018334Speter     If so, return 1.  */
222118334Speter  if (code == GET_CODE (y))
222218334Speter    {
222318334Speter      if (exp_equiv_p (x, y, 0, 1))
222418334Speter	return 1;
222518334Speter    }
222618334Speter
222718334Speter  /* X does not match, so try its subexpressions.  */
222818334Speter
222918334Speter  fmt = GET_RTX_FORMAT (code);
223018334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
223118334Speter    if (fmt[i] == 'e')
223218334Speter      {
223318334Speter	if (i == 0)
223418334Speter	  {
223518334Speter	    x = XEXP (x, 0);
223618334Speter	    goto repeat;
223718334Speter	  }
223818334Speter	else
223918334Speter	  if (refers_to_p (XEXP (x, i), y))
224018334Speter	    return 1;
224118334Speter      }
224218334Speter    else if (fmt[i] == 'E')
224318334Speter      {
224418334Speter	int j;
224518334Speter	for (j = 0; j < XVECLEN (x, i); j++)
224618334Speter	  if (refers_to_p (XVECEXP (x, i, j), y))
224718334Speter	    return 1;
224818334Speter      }
224918334Speter
225018334Speter  return 0;
225118334Speter}
225218334Speter
225318334Speter/* Given ADDR and SIZE (a memory address, and the size of the memory reference),
225418334Speter   set PBASE, PSTART, and PEND which correspond to the base of the address,
225518334Speter   the starting offset, and ending offset respectively.
225618334Speter
225718334Speter   ADDR is known to be a nonvarying address.  */
225818334Speter
225918334Speter/* ??? Despite what the comments say, this function is in fact frequently
226018334Speter   passed varying addresses.  This does not appear to cause any problems.  */
226118334Speter
226218334Speterstatic void
226318334Speterset_nonvarying_address_components (addr, size, pbase, pstart, pend)
226418334Speter     rtx addr;
226518334Speter     int size;
226618334Speter     rtx *pbase;
226718334Speter     HOST_WIDE_INT *pstart, *pend;
226818334Speter{
226918334Speter  rtx base;
227018334Speter  HOST_WIDE_INT start, end;
227118334Speter
227218334Speter  base = addr;
227318334Speter  start = 0;
227418334Speter  end = 0;
227518334Speter
227618334Speter  /* Registers with nonvarying addresses usually have constant equivalents;
227718334Speter     but the frame pointer register is also possible.  */
227818334Speter  if (GET_CODE (base) == REG
227918334Speter      && qty_const != 0
228018334Speter      && REGNO_QTY_VALID_P (REGNO (base))
228118334Speter      && qty_mode[reg_qty[REGNO (base)]] == GET_MODE (base)
228218334Speter      && qty_const[reg_qty[REGNO (base)]] != 0)
228318334Speter    base = qty_const[reg_qty[REGNO (base)]];
228418334Speter  else if (GET_CODE (base) == PLUS
228518334Speter	   && GET_CODE (XEXP (base, 1)) == CONST_INT
228618334Speter	   && GET_CODE (XEXP (base, 0)) == REG
228718334Speter	   && qty_const != 0
228818334Speter	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
228918334Speter	   && (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
229018334Speter	       == GET_MODE (XEXP (base, 0)))
229118334Speter	   && qty_const[reg_qty[REGNO (XEXP (base, 0))]])
229218334Speter    {
229318334Speter      start = INTVAL (XEXP (base, 1));
229418334Speter      base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
229518334Speter    }
229618334Speter  /* This can happen as the result of virtual register instantiation,
229718334Speter     if the initial offset is too large to be a valid address.  */
229818334Speter  else if (GET_CODE (base) == PLUS
229918334Speter	   && GET_CODE (XEXP (base, 0)) == REG
230018334Speter	   && GET_CODE (XEXP (base, 1)) == REG
230118334Speter	   && qty_const != 0
230218334Speter	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 0)))
230318334Speter	   && (qty_mode[reg_qty[REGNO (XEXP (base, 0))]]
230418334Speter	       == GET_MODE (XEXP (base, 0)))
230518334Speter	   && qty_const[reg_qty[REGNO (XEXP (base, 0))]]
230618334Speter	   && REGNO_QTY_VALID_P (REGNO (XEXP (base, 1)))
230718334Speter	   && (qty_mode[reg_qty[REGNO (XEXP (base, 1))]]
230818334Speter	       == GET_MODE (XEXP (base, 1)))
230918334Speter	   && qty_const[reg_qty[REGNO (XEXP (base, 1))]])
231018334Speter    {
231118334Speter      rtx tem = qty_const[reg_qty[REGNO (XEXP (base, 1))]];
231218334Speter      base = qty_const[reg_qty[REGNO (XEXP (base, 0))]];
231318334Speter
231418334Speter      /* One of the two values must be a constant.  */
231518334Speter      if (GET_CODE (base) != CONST_INT)
231618334Speter	{
231718334Speter	  if (GET_CODE (tem) != CONST_INT)
231818334Speter	    abort ();
231918334Speter	  start = INTVAL (tem);
232018334Speter	}
232118334Speter      else
232218334Speter	{
232318334Speter	  start = INTVAL (base);
232418334Speter	  base = tem;
232518334Speter	}
232618334Speter    }
232718334Speter
232818334Speter  /* Handle everything that we can find inside an address that has been
232918334Speter     viewed as constant.  */
233018334Speter
233118334Speter  while (1)
233218334Speter    {
233318334Speter      /* If no part of this switch does a "continue", the code outside
233418334Speter	 will exit this loop.  */
233518334Speter
233618334Speter      switch (GET_CODE (base))
233718334Speter	{
233818334Speter	case LO_SUM:
233918334Speter	  /* By definition, operand1 of a LO_SUM is the associated constant
234018334Speter	     address.  Use the associated constant address as the base
234118334Speter	     instead.  */
234218334Speter	  base = XEXP (base, 1);
234318334Speter	  continue;
234418334Speter
234518334Speter	case CONST:
234618334Speter	  /* Strip off CONST.  */
234718334Speter	  base = XEXP (base, 0);
234818334Speter	  continue;
234918334Speter
235018334Speter	case PLUS:
235118334Speter	  if (GET_CODE (XEXP (base, 1)) == CONST_INT)
235218334Speter	    {
235318334Speter	      start += INTVAL (XEXP (base, 1));
235418334Speter	      base = XEXP (base, 0);
235518334Speter	      continue;
235618334Speter	    }
235718334Speter	  break;
235818334Speter
235918334Speter	case AND:
236018334Speter	  /* Handle the case of an AND which is the negative of a power of
236118334Speter	     two.  This is used to represent unaligned memory operations.  */
236218334Speter	  if (GET_CODE (XEXP (base, 1)) == CONST_INT
236318334Speter	      && exact_log2 (- INTVAL (XEXP (base, 1))) > 0)
236418334Speter	    {
236518334Speter	      set_nonvarying_address_components (XEXP (base, 0), size,
236618334Speter						 pbase, pstart, pend);
236718334Speter
236818334Speter	      /* Assume the worst misalignment.  START is affected, but not
236918334Speter		 END, so compensate but adjusting SIZE.  Don't lose any
237018334Speter		 constant we already had.  */
237118334Speter
237218334Speter	      size = *pend - *pstart - INTVAL (XEXP (base, 1)) - 1;
237318334Speter	      start += *pstart + INTVAL (XEXP (base, 1)) + 1;
237418334Speter	      end += *pend;
237518334Speter	      base = *pbase;
237618334Speter	    }
237718334Speter	  break;
237818334Speter	}
237918334Speter
238018334Speter      break;
238118334Speter    }
238218334Speter
238318334Speter  if (GET_CODE (base) == CONST_INT)
238418334Speter    {
238518334Speter      start += INTVAL (base);
238618334Speter      base = const0_rtx;
238718334Speter    }
238818334Speter
238918334Speter  end = start + size;
239018334Speter
239118334Speter  /* Set the return values.  */
239218334Speter  *pbase = base;
239318334Speter  *pstart = start;
239418334Speter  *pend = end;
239518334Speter}
239618334Speter
239718334Speter/* Return 1 iff any subexpression of X refers to memory
239818334Speter   at an address of BASE plus some offset
239918334Speter   such that any of the bytes' offsets fall between START (inclusive)
240018334Speter   and END (exclusive).
240118334Speter
240218334Speter   The value is undefined if X is a varying address (as determined by
240318334Speter   cse_rtx_addr_varies_p).  This function is not used in such cases.
240418334Speter
240518334Speter   When used in the cse pass, `qty_const' is nonzero, and it is used
240618334Speter   to treat an address that is a register with a known constant value
240718334Speter   as if it were that constant value.
240818334Speter   In the loop pass, `qty_const' is zero, so this is not done.  */
240918334Speter
241018334Speterstatic int
241118334Speterrefers_to_mem_p (x, base, start, end)
241218334Speter     rtx x, base;
241318334Speter     HOST_WIDE_INT start, end;
241418334Speter{
241518334Speter  register HOST_WIDE_INT i;
241618334Speter  register enum rtx_code code;
241718334Speter  register char *fmt;
241818334Speter
241918334Speter repeat:
242018334Speter  if (x == 0)
242118334Speter    return 0;
242218334Speter
242318334Speter  code = GET_CODE (x);
242418334Speter  if (code == MEM)
242518334Speter    {
242618334Speter      register rtx addr = XEXP (x, 0);	/* Get the address.  */
242718334Speter      rtx mybase;
242818334Speter      HOST_WIDE_INT mystart, myend;
242918334Speter
243018334Speter      set_nonvarying_address_components (addr, GET_MODE_SIZE (GET_MODE (x)),
243118334Speter					 &mybase, &mystart, &myend);
243218334Speter
243318334Speter
243418334Speter      /* refers_to_mem_p is never called with varying addresses.
243518334Speter	 If the base addresses are not equal, there is no chance
243618334Speter	 of the memory addresses conflicting.  */
243718334Speter      if (! rtx_equal_p (mybase, base))
243818334Speter	return 0;
243918334Speter
244018334Speter      return myend > start && mystart < end;
244118334Speter    }
244218334Speter
244318334Speter  /* X does not match, so try its subexpressions.  */
244418334Speter
244518334Speter  fmt = GET_RTX_FORMAT (code);
244618334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
244718334Speter    if (fmt[i] == 'e')
244818334Speter      {
244918334Speter	if (i == 0)
245018334Speter	  {
245118334Speter	    x = XEXP (x, 0);
245218334Speter	    goto repeat;
245318334Speter	  }
245418334Speter	else
245518334Speter	  if (refers_to_mem_p (XEXP (x, i), base, start, end))
245618334Speter	    return 1;
245718334Speter      }
245818334Speter    else if (fmt[i] == 'E')
245918334Speter      {
246018334Speter	int j;
246118334Speter	for (j = 0; j < XVECLEN (x, i); j++)
246218334Speter	  if (refers_to_mem_p (XVECEXP (x, i, j), base, start, end))
246318334Speter	    return 1;
246418334Speter      }
246518334Speter
246618334Speter  return 0;
246718334Speter}
246818334Speter
246918334Speter/* Nonzero if X refers to memory at a varying address;
247018334Speter   except that a register which has at the moment a known constant value
247118334Speter   isn't considered variable.  */
247218334Speter
247318334Speterstatic int
247418334Spetercse_rtx_addr_varies_p (x)
247518334Speter     rtx x;
247618334Speter{
247718334Speter  /* We need not check for X and the equivalence class being of the same
247818334Speter     mode because if X is equivalent to a constant in some mode, it
247918334Speter     doesn't vary in any mode.  */
248018334Speter
248118334Speter  if (GET_CODE (x) == MEM
248218334Speter      && GET_CODE (XEXP (x, 0)) == REG
248318334Speter      && REGNO_QTY_VALID_P (REGNO (XEXP (x, 0)))
248418334Speter      && GET_MODE (XEXP (x, 0)) == qty_mode[reg_qty[REGNO (XEXP (x, 0))]]
248518334Speter      && qty_const[reg_qty[REGNO (XEXP (x, 0))]] != 0)
248618334Speter    return 0;
248718334Speter
248818334Speter  if (GET_CODE (x) == MEM
248918334Speter      && GET_CODE (XEXP (x, 0)) == PLUS
249018334Speter      && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
249118334Speter      && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
249218334Speter      && REGNO_QTY_VALID_P (REGNO (XEXP (XEXP (x, 0), 0)))
249318334Speter      && (GET_MODE (XEXP (XEXP (x, 0), 0))
249418334Speter	  == qty_mode[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]])
249518334Speter      && qty_const[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]])
249618334Speter    return 0;
249718334Speter
249818334Speter  /* This can happen as the result of virtual register instantiation, if
249918334Speter     the initial constant is too large to be a valid address.  This gives
250018334Speter     us a three instruction sequence, load large offset into a register,
250118334Speter     load fp minus a constant into a register, then a MEM which is the
250218334Speter     sum of the two `constant' registers.  */
250318334Speter  if (GET_CODE (x) == MEM
250418334Speter      && GET_CODE (XEXP (x, 0)) == PLUS
250518334Speter      && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
250618334Speter      && GET_CODE (XEXP (XEXP (x, 0), 1)) == REG
250718334Speter      && REGNO_QTY_VALID_P (REGNO (XEXP (XEXP (x, 0), 0)))
250818334Speter      && (GET_MODE (XEXP (XEXP (x, 0), 0))
250918334Speter	  == qty_mode[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]])
251018334Speter      && qty_const[reg_qty[REGNO (XEXP (XEXP (x, 0), 0))]]
251118334Speter      && REGNO_QTY_VALID_P (REGNO (XEXP (XEXP (x, 0), 1)))
251218334Speter      && (GET_MODE (XEXP (XEXP (x, 0), 1))
251318334Speter	  == qty_mode[reg_qty[REGNO (XEXP (XEXP (x, 0), 1))]])
251418334Speter      && qty_const[reg_qty[REGNO (XEXP (XEXP (x, 0), 1))]])
251518334Speter    return 0;
251618334Speter
251718334Speter  return rtx_addr_varies_p (x);
251818334Speter}
251918334Speter
252018334Speter/* Canonicalize an expression:
252118334Speter   replace each register reference inside it
252218334Speter   with the "oldest" equivalent register.
252318334Speter
252418334Speter   If INSN is non-zero and we are replacing a pseudo with a hard register
252518334Speter   or vice versa, validate_change is used to ensure that INSN remains valid
252618334Speter   after we make our substitution.  The calls are made with IN_GROUP non-zero
252718334Speter   so apply_change_group must be called upon the outermost return from this
252818334Speter   function (unless INSN is zero).  The result of apply_change_group can
252918334Speter   generally be discarded since the changes we are making are optional.  */
253018334Speter
253118334Speterstatic rtx
253218334Spetercanon_reg (x, insn)
253318334Speter     rtx x;
253418334Speter     rtx insn;
253518334Speter{
253618334Speter  register int i;
253718334Speter  register enum rtx_code code;
253818334Speter  register char *fmt;
253918334Speter
254018334Speter  if (x == 0)
254118334Speter    return x;
254218334Speter
254318334Speter  code = GET_CODE (x);
254418334Speter  switch (code)
254518334Speter    {
254618334Speter    case PC:
254718334Speter    case CC0:
254818334Speter    case CONST:
254918334Speter    case CONST_INT:
255018334Speter    case CONST_DOUBLE:
255118334Speter    case SYMBOL_REF:
255218334Speter    case LABEL_REF:
255318334Speter    case ADDR_VEC:
255418334Speter    case ADDR_DIFF_VEC:
255518334Speter      return x;
255618334Speter
255718334Speter    case REG:
255818334Speter      {
255918334Speter	register int first;
256018334Speter
256118334Speter	/* Never replace a hard reg, because hard regs can appear
256218334Speter	   in more than one machine mode, and we must preserve the mode
256318334Speter	   of each occurrence.  Also, some hard regs appear in
256418334Speter	   MEMs that are shared and mustn't be altered.  Don't try to
256518334Speter	   replace any reg that maps to a reg of class NO_REGS.  */
256618334Speter	if (REGNO (x) < FIRST_PSEUDO_REGISTER
256718334Speter	    || ! REGNO_QTY_VALID_P (REGNO (x)))
256818334Speter	  return x;
256918334Speter
257018334Speter	first = qty_first_reg[reg_qty[REGNO (x)]];
257118334Speter	return (first >= FIRST_PSEUDO_REGISTER ? regno_reg_rtx[first]
257218334Speter		: REGNO_REG_CLASS (first) == NO_REGS ? x
257318334Speter		: gen_rtx (REG, qty_mode[reg_qty[REGNO (x)]], first));
257418334Speter      }
257518334Speter    }
257618334Speter
257718334Speter  fmt = GET_RTX_FORMAT (code);
257818334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
257918334Speter    {
258018334Speter      register int j;
258118334Speter
258218334Speter      if (fmt[i] == 'e')
258318334Speter	{
258418334Speter	  rtx new = canon_reg (XEXP (x, i), insn);
258518334Speter
258618334Speter	  /* If replacing pseudo with hard reg or vice versa, ensure the
258718334Speter	     insn remains valid.  Likewise if the insn has MATCH_DUPs.  */
258818334Speter	  if (insn != 0 && new != 0
258918334Speter	      && GET_CODE (new) == REG && GET_CODE (XEXP (x, i)) == REG
259018334Speter	      && (((REGNO (new) < FIRST_PSEUDO_REGISTER)
259118334Speter		   != (REGNO (XEXP (x, i)) < FIRST_PSEUDO_REGISTER))
259218334Speter		  || insn_n_dups[recog_memoized (insn)] > 0))
259318334Speter	    validate_change (insn, &XEXP (x, i), new, 1);
259418334Speter	  else
259518334Speter	    XEXP (x, i) = new;
259618334Speter	}
259718334Speter      else if (fmt[i] == 'E')
259818334Speter	for (j = 0; j < XVECLEN (x, i); j++)
259918334Speter	  XVECEXP (x, i, j) = canon_reg (XVECEXP (x, i, j), insn);
260018334Speter    }
260118334Speter
260218334Speter  return x;
260318334Speter}
260418334Speter
260518334Speter/* LOC is a location with INSN that is an operand address (the contents of
260618334Speter   a MEM).  Find the best equivalent address to use that is valid for this
260718334Speter   insn.
260818334Speter
260918334Speter   On most CISC machines, complicated address modes are costly, and rtx_cost
261018334Speter   is a good approximation for that cost.  However, most RISC machines have
261118334Speter   only a few (usually only one) memory reference formats.  If an address is
261218334Speter   valid at all, it is often just as cheap as any other address.  Hence, for
261318334Speter   RISC machines, we use the configuration macro `ADDRESS_COST' to compare the
261418334Speter   costs of various addresses.  For two addresses of equal cost, choose the one
261518334Speter   with the highest `rtx_cost' value as that has the potential of eliminating
261618334Speter   the most insns.  For equal costs, we choose the first in the equivalence
261718334Speter   class.  Note that we ignore the fact that pseudo registers are cheaper
261818334Speter   than hard registers here because we would also prefer the pseudo registers.
261918334Speter  */
262018334Speter
262118334Speterstatic void
262218334Speterfind_best_addr (insn, loc)
262318334Speter     rtx insn;
262418334Speter     rtx *loc;
262518334Speter{
262618334Speter  struct table_elt *elt, *p;
262718334Speter  rtx addr = *loc;
262818334Speter  int our_cost;
262918334Speter  int found_better = 1;
263018334Speter  int save_do_not_record = do_not_record;
263118334Speter  int save_hash_arg_in_memory = hash_arg_in_memory;
263218334Speter  int save_hash_arg_in_struct = hash_arg_in_struct;
263318334Speter  int addr_volatile;
263418334Speter  int regno;
263518334Speter  unsigned hash;
263618334Speter
263718334Speter  /* Do not try to replace constant addresses or addresses of local and
263818334Speter     argument slots.  These MEM expressions are made only once and inserted
263918334Speter     in many instructions, as well as being used to control symbol table
264018334Speter     output.  It is not safe to clobber them.
264118334Speter
264218334Speter     There are some uncommon cases where the address is already in a register
264318334Speter     for some reason, but we cannot take advantage of that because we have
264418334Speter     no easy way to unshare the MEM.  In addition, looking up all stack
264518334Speter     addresses is costly.  */
264618334Speter  if ((GET_CODE (addr) == PLUS
264718334Speter       && GET_CODE (XEXP (addr, 0)) == REG
264818334Speter       && GET_CODE (XEXP (addr, 1)) == CONST_INT
264918334Speter       && (regno = REGNO (XEXP (addr, 0)),
265018334Speter	   regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM
265118334Speter	   || regno == ARG_POINTER_REGNUM))
265218334Speter      || (GET_CODE (addr) == REG
265318334Speter	  && (regno = REGNO (addr), regno == FRAME_POINTER_REGNUM
265418334Speter	      || regno == HARD_FRAME_POINTER_REGNUM
265518334Speter	      || regno == ARG_POINTER_REGNUM))
265618334Speter      || CONSTANT_ADDRESS_P (addr))
265718334Speter    return;
265818334Speter
265918334Speter  /* If this address is not simply a register, try to fold it.  This will
266018334Speter     sometimes simplify the expression.  Many simplifications
266118334Speter     will not be valid, but some, usually applying the associative rule, will
266218334Speter     be valid and produce better code.  */
266318334Speter  if (GET_CODE (addr) != REG
266418334Speter      && validate_change (insn, loc, fold_rtx (addr, insn), 0))
266518334Speter    addr = *loc;
266618334Speter
266718334Speter  /* If this address is not in the hash table, we can't look for equivalences
266818334Speter     of the whole address.  Also, ignore if volatile.  */
266918334Speter
267018334Speter  do_not_record = 0;
267118334Speter  hash = HASH (addr, Pmode);
267218334Speter  addr_volatile = do_not_record;
267318334Speter  do_not_record = save_do_not_record;
267418334Speter  hash_arg_in_memory = save_hash_arg_in_memory;
267518334Speter  hash_arg_in_struct = save_hash_arg_in_struct;
267618334Speter
267718334Speter  if (addr_volatile)
267818334Speter    return;
267918334Speter
268018334Speter  elt = lookup (addr, hash, Pmode);
268118334Speter
268218334Speter#ifndef ADDRESS_COST
268318334Speter  if (elt)
268418334Speter    {
268518334Speter      our_cost = elt->cost;
268618334Speter
268718334Speter      /* Find the lowest cost below ours that works.  */
268818334Speter      for (elt = elt->first_same_value; elt; elt = elt->next_same_value)
268918334Speter	if (elt->cost < our_cost
269018334Speter	    && (GET_CODE (elt->exp) == REG
269118334Speter		|| exp_equiv_p (elt->exp, elt->exp, 1, 0))
269218334Speter	    && validate_change (insn, loc,
269318334Speter				canon_reg (copy_rtx (elt->exp), NULL_RTX), 0))
269418334Speter	  return;
269518334Speter    }
269618334Speter#else
269718334Speter
269818334Speter  if (elt)
269918334Speter    {
270018334Speter      /* We need to find the best (under the criteria documented above) entry
270118334Speter	 in the class that is valid.  We use the `flag' field to indicate
270218334Speter	 choices that were invalid and iterate until we can't find a better
270318334Speter	 one that hasn't already been tried.  */
270418334Speter
270518334Speter      for (p = elt->first_same_value; p; p = p->next_same_value)
270618334Speter	p->flag = 0;
270718334Speter
270818334Speter      while (found_better)
270918334Speter	{
271018334Speter	  int best_addr_cost = ADDRESS_COST (*loc);
271118334Speter	  int best_rtx_cost = (elt->cost + 1) >> 1;
271218334Speter	  struct table_elt *best_elt = elt;
271318334Speter
271418334Speter	  found_better = 0;
271518334Speter	  for (p = elt->first_same_value; p; p = p->next_same_value)
271618334Speter	    if (! p->flag
271718334Speter		&& (GET_CODE (p->exp) == REG
271818334Speter		    || exp_equiv_p (p->exp, p->exp, 1, 0))
271918334Speter		&& (ADDRESS_COST (p->exp) < best_addr_cost
272018334Speter		    || (ADDRESS_COST (p->exp) == best_addr_cost
272118334Speter			&& (p->cost + 1) >> 1 > best_rtx_cost)))
272218334Speter	      {
272318334Speter		found_better = 1;
272418334Speter		best_addr_cost = ADDRESS_COST (p->exp);
272518334Speter		best_rtx_cost = (p->cost + 1) >> 1;
272618334Speter		best_elt = p;
272718334Speter	      }
272818334Speter
272918334Speter	  if (found_better)
273018334Speter	    {
273118334Speter	      if (validate_change (insn, loc,
273218334Speter				   canon_reg (copy_rtx (best_elt->exp),
273318334Speter					      NULL_RTX), 0))
273418334Speter		return;
273518334Speter	      else
273618334Speter		best_elt->flag = 1;
273718334Speter	    }
273818334Speter	}
273918334Speter    }
274018334Speter
274118334Speter  /* If the address is a binary operation with the first operand a register
274218334Speter     and the second a constant, do the same as above, but looking for
274318334Speter     equivalences of the register.  Then try to simplify before checking for
274418334Speter     the best address to use.  This catches a few cases:  First is when we
274518334Speter     have REG+const and the register is another REG+const.  We can often merge
274618334Speter     the constants and eliminate one insn and one register.  It may also be
274718334Speter     that a machine has a cheap REG+REG+const.  Finally, this improves the
274818334Speter     code on the Alpha for unaligned byte stores.  */
274918334Speter
275018334Speter  if (flag_expensive_optimizations
275118334Speter      && (GET_RTX_CLASS (GET_CODE (*loc)) == '2'
275218334Speter	  || GET_RTX_CLASS (GET_CODE (*loc)) == 'c')
275318334Speter      && GET_CODE (XEXP (*loc, 0)) == REG
275418334Speter      && GET_CODE (XEXP (*loc, 1)) == CONST_INT)
275518334Speter    {
275618334Speter      rtx c = XEXP (*loc, 1);
275718334Speter
275818334Speter      do_not_record = 0;
275918334Speter      hash = HASH (XEXP (*loc, 0), Pmode);
276018334Speter      do_not_record = save_do_not_record;
276118334Speter      hash_arg_in_memory = save_hash_arg_in_memory;
276218334Speter      hash_arg_in_struct = save_hash_arg_in_struct;
276318334Speter
276418334Speter      elt = lookup (XEXP (*loc, 0), hash, Pmode);
276518334Speter      if (elt == 0)
276618334Speter	return;
276718334Speter
276818334Speter      /* We need to find the best (under the criteria documented above) entry
276918334Speter	 in the class that is valid.  We use the `flag' field to indicate
277018334Speter	 choices that were invalid and iterate until we can't find a better
277118334Speter	 one that hasn't already been tried.  */
277218334Speter
277318334Speter      for (p = elt->first_same_value; p; p = p->next_same_value)
277418334Speter	p->flag = 0;
277518334Speter
277618334Speter      while (found_better)
277718334Speter	{
277818334Speter	  int best_addr_cost = ADDRESS_COST (*loc);
277918334Speter	  int best_rtx_cost = (COST (*loc) + 1) >> 1;
278018334Speter	  struct table_elt *best_elt = elt;
278118334Speter	  rtx best_rtx = *loc;
278218334Speter	  int count;
278318334Speter
278418334Speter	  /* This is at worst case an O(n^2) algorithm, so limit our search
278518334Speter	     to the first 32 elements on the list.  This avoids trouble
278618334Speter	     compiling code with very long basic blocks that can easily
278718334Speter	     call cse_gen_binary so many times that we run out of memory.  */
278818334Speter
278918334Speter	  found_better = 0;
279018334Speter	  for (p = elt->first_same_value, count = 0;
279118334Speter	       p && count < 32;
279218334Speter	       p = p->next_same_value, count++)
279318334Speter	    if (! p->flag
279418334Speter		&& (GET_CODE (p->exp) == REG
279518334Speter		    || exp_equiv_p (p->exp, p->exp, 1, 0)))
279618334Speter	      {
279718334Speter		rtx new = cse_gen_binary (GET_CODE (*loc), Pmode, p->exp, c);
279818334Speter
279918334Speter		if ((ADDRESS_COST (new) < best_addr_cost
280018334Speter		    || (ADDRESS_COST (new) == best_addr_cost
280118334Speter			&& (COST (new) + 1) >> 1 > best_rtx_cost)))
280218334Speter		  {
280318334Speter		    found_better = 1;
280418334Speter		    best_addr_cost = ADDRESS_COST (new);
280518334Speter		    best_rtx_cost = (COST (new) + 1) >> 1;
280618334Speter		    best_elt = p;
280718334Speter		    best_rtx = new;
280818334Speter		  }
280918334Speter	      }
281018334Speter
281118334Speter	  if (found_better)
281218334Speter	    {
281318334Speter	      if (validate_change (insn, loc,
281418334Speter				   canon_reg (copy_rtx (best_rtx),
281518334Speter					      NULL_RTX), 0))
281618334Speter		return;
281718334Speter	      else
281818334Speter		best_elt->flag = 1;
281918334Speter	    }
282018334Speter	}
282118334Speter    }
282218334Speter#endif
282318334Speter}
282418334Speter
282518334Speter/* Given an operation (CODE, *PARG1, *PARG2), where code is a comparison
282618334Speter   operation (EQ, NE, GT, etc.), follow it back through the hash table and
282718334Speter   what values are being compared.
282818334Speter
282918334Speter   *PARG1 and *PARG2 are updated to contain the rtx representing the values
283018334Speter   actually being compared.  For example, if *PARG1 was (cc0) and *PARG2
283118334Speter   was (const_int 0), *PARG1 and *PARG2 will be set to the objects that were
283218334Speter   compared to produce cc0.
283318334Speter
283418334Speter   The return value is the comparison operator and is either the code of
283518334Speter   A or the code corresponding to the inverse of the comparison.  */
283618334Speter
283718334Speterstatic enum rtx_code
283818334Speterfind_comparison_args (code, parg1, parg2, pmode1, pmode2)
283918334Speter     enum rtx_code code;
284018334Speter     rtx *parg1, *parg2;
284118334Speter     enum machine_mode *pmode1, *pmode2;
284218334Speter{
284318334Speter  rtx arg1, arg2;
284418334Speter
284518334Speter  arg1 = *parg1, arg2 = *parg2;
284618334Speter
284718334Speter  /* If ARG2 is const0_rtx, see what ARG1 is equivalent to.  */
284818334Speter
284918334Speter  while (arg2 == CONST0_RTX (GET_MODE (arg1)))
285018334Speter    {
285118334Speter      /* Set non-zero when we find something of interest.  */
285218334Speter      rtx x = 0;
285318334Speter      int reverse_code = 0;
285418334Speter      struct table_elt *p = 0;
285518334Speter
285618334Speter      /* If arg1 is a COMPARE, extract the comparison arguments from it.
285718334Speter	 On machines with CC0, this is the only case that can occur, since
285818334Speter	 fold_rtx will return the COMPARE or item being compared with zero
285918334Speter	 when given CC0.  */
286018334Speter
286118334Speter      if (GET_CODE (arg1) == COMPARE && arg2 == const0_rtx)
286218334Speter	x = arg1;
286318334Speter
286418334Speter      /* If ARG1 is a comparison operator and CODE is testing for
286518334Speter	 STORE_FLAG_VALUE, get the inner arguments.  */
286618334Speter
286718334Speter      else if (GET_RTX_CLASS (GET_CODE (arg1)) == '<')
286818334Speter	{
286918334Speter	  if (code == NE
287018334Speter	      || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT
287118334Speter		  && code == LT && STORE_FLAG_VALUE == -1)
287218334Speter#ifdef FLOAT_STORE_FLAG_VALUE
287318334Speter	      || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
287418334Speter		  && FLOAT_STORE_FLAG_VALUE < 0)
287518334Speter#endif
287618334Speter	      )
287718334Speter	    x = arg1;
287818334Speter	  else if (code == EQ
287918334Speter		   || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_INT
288018334Speter		       && code == GE && STORE_FLAG_VALUE == -1)
288118334Speter#ifdef FLOAT_STORE_FLAG_VALUE
288218334Speter		   || (GET_MODE_CLASS (GET_MODE (arg1)) == MODE_FLOAT
288318334Speter		       && FLOAT_STORE_FLAG_VALUE < 0)
288418334Speter#endif
288518334Speter		   )
288618334Speter	    x = arg1, reverse_code = 1;
288718334Speter	}
288818334Speter
288918334Speter      /* ??? We could also check for
289018334Speter
289118334Speter	 (ne (and (eq (...) (const_int 1))) (const_int 0))
289218334Speter
289318334Speter	 and related forms, but let's wait until we see them occurring.  */
289418334Speter
289518334Speter      if (x == 0)
289618334Speter	/* Look up ARG1 in the hash table and see if it has an equivalence
289718334Speter	   that lets us see what is being compared.  */
289818334Speter	p = lookup (arg1, safe_hash (arg1, GET_MODE (arg1)) % NBUCKETS,
289918334Speter		    GET_MODE (arg1));
290018334Speter      if (p) p = p->first_same_value;
290118334Speter
290218334Speter      for (; p; p = p->next_same_value)
290318334Speter	{
290418334Speter	  enum machine_mode inner_mode = GET_MODE (p->exp);
290518334Speter
290618334Speter	  /* If the entry isn't valid, skip it.  */
290718334Speter	  if (! exp_equiv_p (p->exp, p->exp, 1, 0))
290818334Speter	    continue;
290918334Speter
291018334Speter	  if (GET_CODE (p->exp) == COMPARE
291118334Speter	      /* Another possibility is that this machine has a compare insn
291218334Speter		 that includes the comparison code.  In that case, ARG1 would
291318334Speter		 be equivalent to a comparison operation that would set ARG1 to
291418334Speter		 either STORE_FLAG_VALUE or zero.  If this is an NE operation,
291518334Speter		 ORIG_CODE is the actual comparison being done; if it is an EQ,
291618334Speter		 we must reverse ORIG_CODE.  On machine with a negative value
291718334Speter		 for STORE_FLAG_VALUE, also look at LT and GE operations.  */
291818334Speter	      || ((code == NE
291918334Speter		   || (code == LT
292018334Speter		       && GET_MODE_CLASS (inner_mode) == MODE_INT
292118334Speter		       && (GET_MODE_BITSIZE (inner_mode)
292218334Speter			   <= HOST_BITS_PER_WIDE_INT)
292318334Speter		       && (STORE_FLAG_VALUE
292418334Speter			   & ((HOST_WIDE_INT) 1
292518334Speter			      << (GET_MODE_BITSIZE (inner_mode) - 1))))
292618334Speter#ifdef FLOAT_STORE_FLAG_VALUE
292718334Speter		   || (code == LT
292818334Speter		       && GET_MODE_CLASS (inner_mode) == MODE_FLOAT
292918334Speter		       && FLOAT_STORE_FLAG_VALUE < 0)
293018334Speter#endif
293118334Speter		   )
293218334Speter		  && GET_RTX_CLASS (GET_CODE (p->exp)) == '<'))
293318334Speter	    {
293418334Speter	      x = p->exp;
293518334Speter	      break;
293618334Speter	    }
293718334Speter	  else if ((code == EQ
293818334Speter		    || (code == GE
293918334Speter			&& GET_MODE_CLASS (inner_mode) == MODE_INT
294018334Speter			&& (GET_MODE_BITSIZE (inner_mode)
294118334Speter			    <= HOST_BITS_PER_WIDE_INT)
294218334Speter			&& (STORE_FLAG_VALUE
294318334Speter			    & ((HOST_WIDE_INT) 1
294418334Speter			       << (GET_MODE_BITSIZE (inner_mode) - 1))))
294518334Speter#ifdef FLOAT_STORE_FLAG_VALUE
294618334Speter		    || (code == GE
294718334Speter			&& GET_MODE_CLASS (inner_mode) == MODE_FLOAT
294818334Speter			&& FLOAT_STORE_FLAG_VALUE < 0)
294918334Speter#endif
295018334Speter		    )
295118334Speter		   && GET_RTX_CLASS (GET_CODE (p->exp)) == '<')
295218334Speter	    {
295318334Speter	      reverse_code = 1;
295418334Speter	      x = p->exp;
295518334Speter	      break;
295618334Speter	    }
295718334Speter
295818334Speter	  /* If this is fp + constant, the equivalent is a better operand since
295918334Speter	     it may let us predict the value of the comparison.  */
296018334Speter	  else if (NONZERO_BASE_PLUS_P (p->exp))
296118334Speter	    {
296218334Speter	      arg1 = p->exp;
296318334Speter	      continue;
296418334Speter	    }
296518334Speter	}
296618334Speter
296718334Speter      /* If we didn't find a useful equivalence for ARG1, we are done.
296818334Speter	 Otherwise, set up for the next iteration.  */
296918334Speter      if (x == 0)
297018334Speter	break;
297118334Speter
297218334Speter      arg1 = XEXP (x, 0),  arg2 = XEXP (x, 1);
297318334Speter      if (GET_RTX_CLASS (GET_CODE (x)) == '<')
297418334Speter	code = GET_CODE (x);
297518334Speter
297618334Speter      if (reverse_code)
297718334Speter	code = reverse_condition (code);
297818334Speter    }
297918334Speter
298018334Speter  /* Return our results.  Return the modes from before fold_rtx
298118334Speter     because fold_rtx might produce const_int, and then it's too late.  */
298218334Speter  *pmode1 = GET_MODE (arg1), *pmode2 = GET_MODE (arg2);
298318334Speter  *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
298418334Speter
298518334Speter  return code;
298618334Speter}
298718334Speter
298818334Speter/* Try to simplify a unary operation CODE whose output mode is to be
298918334Speter   MODE with input operand OP whose mode was originally OP_MODE.
299018334Speter   Return zero if no simplification can be made.  */
299118334Speter
299218334Speterrtx
299318334Spetersimplify_unary_operation (code, mode, op, op_mode)
299418334Speter     enum rtx_code code;
299518334Speter     enum machine_mode mode;
299618334Speter     rtx op;
299718334Speter     enum machine_mode op_mode;
299818334Speter{
299918334Speter  register int width = GET_MODE_BITSIZE (mode);
300018334Speter
300118334Speter  /* The order of these tests is critical so that, for example, we don't
300218334Speter     check the wrong mode (input vs. output) for a conversion operation,
300318334Speter     such as FIX.  At some point, this should be simplified.  */
300418334Speter
300518334Speter#if !defined(REAL_IS_NOT_DOUBLE) || defined(REAL_ARITHMETIC)
300618334Speter
300718334Speter  if (code == FLOAT && GET_MODE (op) == VOIDmode
300818334Speter      && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
300918334Speter    {
301018334Speter      HOST_WIDE_INT hv, lv;
301118334Speter      REAL_VALUE_TYPE d;
301218334Speter
301318334Speter      if (GET_CODE (op) == CONST_INT)
301418334Speter	lv = INTVAL (op), hv = INTVAL (op) < 0 ? -1 : 0;
301518334Speter      else
301618334Speter	lv = CONST_DOUBLE_LOW (op),  hv = CONST_DOUBLE_HIGH (op);
301718334Speter
301818334Speter#ifdef REAL_ARITHMETIC
301918334Speter      REAL_VALUE_FROM_INT (d, lv, hv);
302018334Speter#else
302118334Speter      if (hv < 0)
302218334Speter	{
302318334Speter	  d = (double) (~ hv);
302418334Speter	  d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
302518334Speter		* (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
302618334Speter	  d += (double) (unsigned HOST_WIDE_INT) (~ lv);
302718334Speter	  d = (- d - 1.0);
302818334Speter	}
302918334Speter      else
303018334Speter	{
303118334Speter	  d = (double) hv;
303218334Speter	  d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
303318334Speter		* (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
303418334Speter	  d += (double) (unsigned HOST_WIDE_INT) lv;
303518334Speter	}
303618334Speter#endif  /* REAL_ARITHMETIC */
303718334Speter      d = real_value_truncate (mode, d);
303818334Speter      return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
303918334Speter    }
304018334Speter  else if (code == UNSIGNED_FLOAT && GET_MODE (op) == VOIDmode
304118334Speter	   && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
304218334Speter    {
304318334Speter      HOST_WIDE_INT hv, lv;
304418334Speter      REAL_VALUE_TYPE d;
304518334Speter
304618334Speter      if (GET_CODE (op) == CONST_INT)
304718334Speter	lv = INTVAL (op), hv = INTVAL (op) < 0 ? -1 : 0;
304818334Speter      else
304918334Speter	lv = CONST_DOUBLE_LOW (op),  hv = CONST_DOUBLE_HIGH (op);
305018334Speter
305118334Speter      if (op_mode == VOIDmode)
305218334Speter	{
305318334Speter	  /* We don't know how to interpret negative-looking numbers in
305418334Speter	     this case, so don't try to fold those.  */
305518334Speter	  if (hv < 0)
305618334Speter	    return 0;
305718334Speter	}
305818334Speter      else if (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT * 2)
305918334Speter	;
306018334Speter      else
306118334Speter	hv = 0, lv &= GET_MODE_MASK (op_mode);
306218334Speter
306318334Speter#ifdef REAL_ARITHMETIC
306418334Speter      REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv);
306518334Speter#else
306618334Speter
306718334Speter      d = (double) (unsigned HOST_WIDE_INT) hv;
306818334Speter      d *= ((double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2))
306918334Speter	    * (double) ((HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 2)));
307018334Speter      d += (double) (unsigned HOST_WIDE_INT) lv;
307118334Speter#endif  /* REAL_ARITHMETIC */
307218334Speter      d = real_value_truncate (mode, d);
307318334Speter      return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
307418334Speter    }
307518334Speter#endif
307618334Speter
307718334Speter  if (GET_CODE (op) == CONST_INT
307818334Speter      && width <= HOST_BITS_PER_WIDE_INT && width > 0)
307918334Speter    {
308018334Speter      register HOST_WIDE_INT arg0 = INTVAL (op);
308118334Speter      register HOST_WIDE_INT val;
308218334Speter
308318334Speter      switch (code)
308418334Speter	{
308518334Speter	case NOT:
308618334Speter	  val = ~ arg0;
308718334Speter	  break;
308818334Speter
308918334Speter	case NEG:
309018334Speter	  val = - arg0;
309118334Speter	  break;
309218334Speter
309318334Speter	case ABS:
309418334Speter	  val = (arg0 >= 0 ? arg0 : - arg0);
309518334Speter	  break;
309618334Speter
309718334Speter	case FFS:
309818334Speter	  /* Don't use ffs here.  Instead, get low order bit and then its
309918334Speter	     number.  If arg0 is zero, this will return 0, as desired.  */
310018334Speter	  arg0 &= GET_MODE_MASK (mode);
310118334Speter	  val = exact_log2 (arg0 & (- arg0)) + 1;
310218334Speter	  break;
310318334Speter
310418334Speter	case TRUNCATE:
310518334Speter	  val = arg0;
310618334Speter	  break;
310718334Speter
310818334Speter	case ZERO_EXTEND:
310918334Speter	  if (op_mode == VOIDmode)
311018334Speter	    op_mode = mode;
311118334Speter	  if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
311218334Speter	    {
311318334Speter	      /* If we were really extending the mode,
311418334Speter		 we would have to distinguish between zero-extension
311518334Speter		 and sign-extension.  */
311618334Speter	      if (width != GET_MODE_BITSIZE (op_mode))
311718334Speter		abort ();
311818334Speter	      val = arg0;
311918334Speter	    }
312018334Speter	  else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
312118334Speter	    val = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode));
312218334Speter	  else
312318334Speter	    return 0;
312418334Speter	  break;
312518334Speter
312618334Speter	case SIGN_EXTEND:
312718334Speter	  if (op_mode == VOIDmode)
312818334Speter	    op_mode = mode;
312918334Speter	  if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
313018334Speter	    {
313118334Speter	      /* If we were really extending the mode,
313218334Speter		 we would have to distinguish between zero-extension
313318334Speter		 and sign-extension.  */
313418334Speter	      if (width != GET_MODE_BITSIZE (op_mode))
313518334Speter		abort ();
313618334Speter	      val = arg0;
313718334Speter	    }
313818334Speter	  else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
313918334Speter	    {
314018334Speter	      val
314118334Speter		= arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode));
314218334Speter	      if (val
314318334Speter		  & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (op_mode) - 1)))
314418334Speter		val -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
314518334Speter	    }
314618334Speter	  else
314718334Speter	    return 0;
314818334Speter	  break;
314918334Speter
315018334Speter	case SQRT:
315118334Speter	  return 0;
315218334Speter
315318334Speter	default:
315418334Speter	  abort ();
315518334Speter	}
315618334Speter
315718334Speter      /* Clear the bits that don't belong in our mode,
315818334Speter	 unless they and our sign bit are all one.
315918334Speter	 So we get either a reasonable negative value or a reasonable
316018334Speter	 unsigned value for this mode.  */
316118334Speter      if (width < HOST_BITS_PER_WIDE_INT
316218334Speter	  && ((val & ((HOST_WIDE_INT) (-1) << (width - 1)))
316318334Speter	      != ((HOST_WIDE_INT) (-1) << (width - 1))))
316418334Speter	val &= ((HOST_WIDE_INT) 1 << width) - 1;
316518334Speter
316618334Speter      return GEN_INT (val);
316718334Speter    }
316818334Speter
316918334Speter  /* We can do some operations on integer CONST_DOUBLEs.  Also allow
317018334Speter     for a DImode operation on a CONST_INT. */
317118334Speter  else if (GET_MODE (op) == VOIDmode && width <= HOST_BITS_PER_INT * 2
317218334Speter	   && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
317318334Speter    {
317418334Speter      HOST_WIDE_INT l1, h1, lv, hv;
317518334Speter
317618334Speter      if (GET_CODE (op) == CONST_DOUBLE)
317718334Speter	l1 = CONST_DOUBLE_LOW (op), h1 = CONST_DOUBLE_HIGH (op);
317818334Speter      else
317918334Speter	l1 = INTVAL (op), h1 = l1 < 0 ? -1 : 0;
318018334Speter
318118334Speter      switch (code)
318218334Speter	{
318318334Speter	case NOT:
318418334Speter	  lv = ~ l1;
318518334Speter	  hv = ~ h1;
318618334Speter	  break;
318718334Speter
318818334Speter	case NEG:
318918334Speter	  neg_double (l1, h1, &lv, &hv);
319018334Speter	  break;
319118334Speter
319218334Speter	case ABS:
319318334Speter	  if (h1 < 0)
319418334Speter	    neg_double (l1, h1, &lv, &hv);
319518334Speter	  else
319618334Speter	    lv = l1, hv = h1;
319718334Speter	  break;
319818334Speter
319918334Speter	case FFS:
320018334Speter	  hv = 0;
320118334Speter	  if (l1 == 0)
320218334Speter	    lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & (-h1)) + 1;
320318334Speter	  else
320418334Speter	    lv = exact_log2 (l1 & (-l1)) + 1;
320518334Speter	  break;
320618334Speter
320718334Speter	case TRUNCATE:
320818334Speter	  /* This is just a change-of-mode, so do nothing.  */
320918334Speter	  lv = l1, hv = h1;
321018334Speter	  break;
321118334Speter
321218334Speter	case ZERO_EXTEND:
321318334Speter	  if (op_mode == VOIDmode
321418334Speter	      || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
321518334Speter	    return 0;
321618334Speter
321718334Speter	  hv = 0;
321818334Speter	  lv = l1 & GET_MODE_MASK (op_mode);
321918334Speter	  break;
322018334Speter
322118334Speter	case SIGN_EXTEND:
322218334Speter	  if (op_mode == VOIDmode
322318334Speter	      || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
322418334Speter	    return 0;
322518334Speter	  else
322618334Speter	    {
322718334Speter	      lv = l1 & GET_MODE_MASK (op_mode);
322818334Speter	      if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT
322918334Speter		  && (lv & ((HOST_WIDE_INT) 1
323018334Speter			    << (GET_MODE_BITSIZE (op_mode) - 1))) != 0)
323118334Speter		lv -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
323218334Speter
323318334Speter	      hv = (lv < 0) ? ~ (HOST_WIDE_INT) 0 : 0;
323418334Speter	    }
323518334Speter	  break;
323618334Speter
323718334Speter	case SQRT:
323818334Speter	  return 0;
323918334Speter
324018334Speter	default:
324118334Speter	  return 0;
324218334Speter	}
324318334Speter
324418334Speter      return immed_double_const (lv, hv, mode);
324518334Speter    }
324618334Speter
324718334Speter#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
324818334Speter  else if (GET_CODE (op) == CONST_DOUBLE
324918334Speter	   && GET_MODE_CLASS (mode) == MODE_FLOAT)
325018334Speter    {
325118334Speter      REAL_VALUE_TYPE d;
325218334Speter      jmp_buf handler;
325318334Speter      rtx x;
325418334Speter
325518334Speter      if (setjmp (handler))
325618334Speter	/* There used to be a warning here, but that is inadvisable.
325718334Speter	   People may want to cause traps, and the natural way
325818334Speter	   to do it should not get a warning.  */
325918334Speter	return 0;
326018334Speter
326118334Speter      set_float_handler (handler);
326218334Speter
326318334Speter      REAL_VALUE_FROM_CONST_DOUBLE (d, op);
326418334Speter
326518334Speter      switch (code)
326618334Speter	{
326718334Speter	case NEG:
326818334Speter	  d = REAL_VALUE_NEGATE (d);
326918334Speter	  break;
327018334Speter
327118334Speter	case ABS:
327218334Speter	  if (REAL_VALUE_NEGATIVE (d))
327318334Speter	    d = REAL_VALUE_NEGATE (d);
327418334Speter	  break;
327518334Speter
327618334Speter	case FLOAT_TRUNCATE:
327718334Speter	  d = real_value_truncate (mode, d);
327818334Speter	  break;
327918334Speter
328018334Speter	case FLOAT_EXTEND:
328118334Speter	  /* All this does is change the mode.  */
328218334Speter	  break;
328318334Speter
328418334Speter	case FIX:
328518334Speter	  d = REAL_VALUE_RNDZINT (d);
328618334Speter	  break;
328718334Speter
328818334Speter	case UNSIGNED_FIX:
328918334Speter	  d = REAL_VALUE_UNSIGNED_RNDZINT (d);
329018334Speter	  break;
329118334Speter
329218334Speter	case SQRT:
329318334Speter	  return 0;
329418334Speter
329518334Speter	default:
329618334Speter	  abort ();
329718334Speter	}
329818334Speter
329918334Speter      x = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
330018334Speter      set_float_handler (NULL_PTR);
330118334Speter      return x;
330218334Speter    }
330318334Speter
330418334Speter  else if (GET_CODE (op) == CONST_DOUBLE
330518334Speter	   && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
330618334Speter	   && GET_MODE_CLASS (mode) == MODE_INT
330718334Speter	   && width <= HOST_BITS_PER_WIDE_INT && width > 0)
330818334Speter    {
330918334Speter      REAL_VALUE_TYPE d;
331018334Speter      jmp_buf handler;
331118334Speter      HOST_WIDE_INT val;
331218334Speter
331318334Speter      if (setjmp (handler))
331418334Speter	return 0;
331518334Speter
331618334Speter      set_float_handler (handler);
331718334Speter
331818334Speter      REAL_VALUE_FROM_CONST_DOUBLE (d, op);
331918334Speter
332018334Speter      switch (code)
332118334Speter	{
332218334Speter	case FIX:
332318334Speter	  val = REAL_VALUE_FIX (d);
332418334Speter	  break;
332518334Speter
332618334Speter	case UNSIGNED_FIX:
332718334Speter	  val = REAL_VALUE_UNSIGNED_FIX (d);
332818334Speter	  break;
332918334Speter
333018334Speter	default:
333118334Speter	  abort ();
333218334Speter	}
333318334Speter
333418334Speter      set_float_handler (NULL_PTR);
333518334Speter
333618334Speter      /* Clear the bits that don't belong in our mode,
333718334Speter	 unless they and our sign bit are all one.
333818334Speter	 So we get either a reasonable negative value or a reasonable
333918334Speter	 unsigned value for this mode.  */
334018334Speter      if (width < HOST_BITS_PER_WIDE_INT
334118334Speter	  && ((val & ((HOST_WIDE_INT) (-1) << (width - 1)))
334218334Speter	      != ((HOST_WIDE_INT) (-1) << (width - 1))))
334318334Speter	val &= ((HOST_WIDE_INT) 1 << width) - 1;
334418334Speter
334518334Speter      /* If this would be an entire word for the target, but is not for
334618334Speter	 the host, then sign-extend on the host so that the number will look
334718334Speter	 the same way on the host that it would on the target.
334818334Speter
334918334Speter	 For example, when building a 64 bit alpha hosted 32 bit sparc
335018334Speter	 targeted compiler, then we want the 32 bit unsigned value -1 to be
335118334Speter	 represented as a 64 bit value -1, and not as 0x00000000ffffffff.
335218334Speter	 The later confuses the sparc backend.  */
335318334Speter
335418334Speter      if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width
335518334Speter	  && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
335618334Speter	val |= ((HOST_WIDE_INT) (-1) << width);
335718334Speter
335818334Speter      return GEN_INT (val);
335918334Speter    }
336018334Speter#endif
336118334Speter  /* This was formerly used only for non-IEEE float.
336218334Speter     eggert@twinsun.com says it is safe for IEEE also.  */
336318334Speter  else
336418334Speter    {
336518334Speter      /* There are some simplifications we can do even if the operands
336618334Speter	 aren't constant.  */
336718334Speter      switch (code)
336818334Speter	{
336918334Speter	case NEG:
337018334Speter	case NOT:
337118334Speter	  /* (not (not X)) == X, similarly for NEG.  */
337218334Speter	  if (GET_CODE (op) == code)
337318334Speter	    return XEXP (op, 0);
337418334Speter	  break;
337518334Speter
337618334Speter	case SIGN_EXTEND:
337718334Speter	  /* (sign_extend (truncate (minus (label_ref L1) (label_ref L2))))
337818334Speter	     becomes just the MINUS if its mode is MODE.  This allows
337918334Speter	     folding switch statements on machines using casesi (such as
338018334Speter	     the Vax).  */
338118334Speter	  if (GET_CODE (op) == TRUNCATE
338218334Speter	      && GET_MODE (XEXP (op, 0)) == mode
338318334Speter	      && GET_CODE (XEXP (op, 0)) == MINUS
338418334Speter	      && GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF
338518334Speter	      && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF)
338618334Speter	    return XEXP (op, 0);
338718334Speter
338818334Speter#ifdef POINTERS_EXTEND_UNSIGNED
338918334Speter	  if (! POINTERS_EXTEND_UNSIGNED
339018334Speter	      && mode == Pmode && GET_MODE (op) == ptr_mode
339118334Speter	      && CONSTANT_P (op))
339218334Speter	    return convert_memory_address (Pmode, op);
339318334Speter#endif
339418334Speter	  break;
339518334Speter
339618334Speter#ifdef POINTERS_EXTEND_UNSIGNED
339718334Speter	case ZERO_EXTEND:
339818334Speter	  if (POINTERS_EXTEND_UNSIGNED
339918334Speter	      && mode == Pmode && GET_MODE (op) == ptr_mode
340018334Speter	      && CONSTANT_P (op))
340118334Speter	    return convert_memory_address (Pmode, op);
340218334Speter	  break;
340318334Speter#endif
340418334Speter	}
340518334Speter
340618334Speter      return 0;
340718334Speter    }
340818334Speter}
340918334Speter
341018334Speter/* Simplify a binary operation CODE with result mode MODE, operating on OP0
341118334Speter   and OP1.  Return 0 if no simplification is possible.
341218334Speter
341318334Speter   Don't use this for relational operations such as EQ or LT.
341418334Speter   Use simplify_relational_operation instead.  */
341518334Speter
341618334Speterrtx
341718334Spetersimplify_binary_operation (code, mode, op0, op1)
341818334Speter     enum rtx_code code;
341918334Speter     enum machine_mode mode;
342018334Speter     rtx op0, op1;
342118334Speter{
342218334Speter  register HOST_WIDE_INT arg0, arg1, arg0s, arg1s;
342318334Speter  HOST_WIDE_INT val;
342418334Speter  int width = GET_MODE_BITSIZE (mode);
342518334Speter  rtx tem;
342618334Speter
342718334Speter  /* Relational operations don't work here.  We must know the mode
342818334Speter     of the operands in order to do the comparison correctly.
342918334Speter     Assuming a full word can give incorrect results.
343018334Speter     Consider comparing 128 with -128 in QImode.  */
343118334Speter
343218334Speter  if (GET_RTX_CLASS (code) == '<')
343318334Speter    abort ();
343418334Speter
343518334Speter#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
343618334Speter  if (GET_MODE_CLASS (mode) == MODE_FLOAT
343718334Speter      && GET_CODE (op0) == CONST_DOUBLE && GET_CODE (op1) == CONST_DOUBLE
343818334Speter      && mode == GET_MODE (op0) && mode == GET_MODE (op1))
343918334Speter    {
344018334Speter      REAL_VALUE_TYPE f0, f1, value;
344118334Speter      jmp_buf handler;
344218334Speter
344318334Speter      if (setjmp (handler))
344418334Speter	return 0;
344518334Speter
344618334Speter      set_float_handler (handler);
344718334Speter
344818334Speter      REAL_VALUE_FROM_CONST_DOUBLE (f0, op0);
344918334Speter      REAL_VALUE_FROM_CONST_DOUBLE (f1, op1);
345018334Speter      f0 = real_value_truncate (mode, f0);
345118334Speter      f1 = real_value_truncate (mode, f1);
345218334Speter
345318334Speter#ifdef REAL_ARITHMETIC
345418334Speter      REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
345518334Speter#else
345618334Speter      switch (code)
345718334Speter	{
345818334Speter	case PLUS:
345918334Speter	  value = f0 + f1;
346018334Speter	  break;
346118334Speter	case MINUS:
346218334Speter	  value = f0 - f1;
346318334Speter	  break;
346418334Speter	case MULT:
346518334Speter	  value = f0 * f1;
346618334Speter	  break;
346718334Speter	case DIV:
346818334Speter#ifndef REAL_INFINITY
346918334Speter	  if (f1 == 0)
347018334Speter	    return 0;
347118334Speter#endif
347218334Speter	  value = f0 / f1;
347318334Speter	  break;
347418334Speter	case SMIN:
347518334Speter	  value = MIN (f0, f1);
347618334Speter	  break;
347718334Speter	case SMAX:
347818334Speter	  value = MAX (f0, f1);
347918334Speter	  break;
348018334Speter	default:
348118334Speter	  abort ();
348218334Speter	}
348318334Speter#endif
348418334Speter
348518334Speter      value = real_value_truncate (mode, value);
348618334Speter      set_float_handler (NULL_PTR);
348718334Speter      return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
348818334Speter    }
348918334Speter#endif  /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
349018334Speter
349118334Speter  /* We can fold some multi-word operations.  */
349218334Speter  if (GET_MODE_CLASS (mode) == MODE_INT
349318334Speter      && width == HOST_BITS_PER_WIDE_INT * 2
349418334Speter      && (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT)
349518334Speter      && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT))
349618334Speter    {
349718334Speter      HOST_WIDE_INT l1, l2, h1, h2, lv, hv;
349818334Speter
349918334Speter      if (GET_CODE (op0) == CONST_DOUBLE)
350018334Speter	l1 = CONST_DOUBLE_LOW (op0), h1 = CONST_DOUBLE_HIGH (op0);
350118334Speter      else
350218334Speter	l1 = INTVAL (op0), h1 = l1 < 0 ? -1 : 0;
350318334Speter
350418334Speter      if (GET_CODE (op1) == CONST_DOUBLE)
350518334Speter	l2 = CONST_DOUBLE_LOW (op1), h2 = CONST_DOUBLE_HIGH (op1);
350618334Speter      else
350718334Speter	l2 = INTVAL (op1), h2 = l2 < 0 ? -1 : 0;
350818334Speter
350918334Speter      switch (code)
351018334Speter	{
351118334Speter	case MINUS:
351218334Speter	  /* A - B == A + (-B).  */
351318334Speter	  neg_double (l2, h2, &lv, &hv);
351418334Speter	  l2 = lv, h2 = hv;
351518334Speter
351618334Speter	  /* .. fall through ... */
351718334Speter
351818334Speter	case PLUS:
351918334Speter	  add_double (l1, h1, l2, h2, &lv, &hv);
352018334Speter	  break;
352118334Speter
352218334Speter	case MULT:
352318334Speter	  mul_double (l1, h1, l2, h2, &lv, &hv);
352418334Speter	  break;
352518334Speter
352618334Speter	case DIV:  case MOD:   case UDIV:  case UMOD:
352718334Speter	  /* We'd need to include tree.h to do this and it doesn't seem worth
352818334Speter	     it.  */
352918334Speter	  return 0;
353018334Speter
353118334Speter	case AND:
353218334Speter	  lv = l1 & l2, hv = h1 & h2;
353318334Speter	  break;
353418334Speter
353518334Speter	case IOR:
353618334Speter	  lv = l1 | l2, hv = h1 | h2;
353718334Speter	  break;
353818334Speter
353918334Speter	case XOR:
354018334Speter	  lv = l1 ^ l2, hv = h1 ^ h2;
354118334Speter	  break;
354218334Speter
354318334Speter	case SMIN:
354418334Speter	  if (h1 < h2
354518334Speter	      || (h1 == h2
354618334Speter		  && ((unsigned HOST_WIDE_INT) l1
354718334Speter		      < (unsigned HOST_WIDE_INT) l2)))
354818334Speter	    lv = l1, hv = h1;
354918334Speter	  else
355018334Speter	    lv = l2, hv = h2;
355118334Speter	  break;
355218334Speter
355318334Speter	case SMAX:
355418334Speter	  if (h1 > h2
355518334Speter	      || (h1 == h2
355618334Speter		  && ((unsigned HOST_WIDE_INT) l1
355718334Speter		      > (unsigned HOST_WIDE_INT) l2)))
355818334Speter	    lv = l1, hv = h1;
355918334Speter	  else
356018334Speter	    lv = l2, hv = h2;
356118334Speter	  break;
356218334Speter
356318334Speter	case UMIN:
356418334Speter	  if ((unsigned HOST_WIDE_INT) h1 < (unsigned HOST_WIDE_INT) h2
356518334Speter	      || (h1 == h2
356618334Speter		  && ((unsigned HOST_WIDE_INT) l1
356718334Speter		      < (unsigned HOST_WIDE_INT) l2)))
356818334Speter	    lv = l1, hv = h1;
356918334Speter	  else
357018334Speter	    lv = l2, hv = h2;
357118334Speter	  break;
357218334Speter
357318334Speter	case UMAX:
357418334Speter	  if ((unsigned HOST_WIDE_INT) h1 > (unsigned HOST_WIDE_INT) h2
357518334Speter	      || (h1 == h2
357618334Speter		  && ((unsigned HOST_WIDE_INT) l1
357718334Speter		      > (unsigned HOST_WIDE_INT) l2)))
357818334Speter	    lv = l1, hv = h1;
357918334Speter	  else
358018334Speter	    lv = l2, hv = h2;
358118334Speter	  break;
358218334Speter
358318334Speter	case LSHIFTRT:   case ASHIFTRT:
358418334Speter	case ASHIFT:
358518334Speter	case ROTATE:     case ROTATERT:
358618334Speter#ifdef SHIFT_COUNT_TRUNCATED
358718334Speter	  if (SHIFT_COUNT_TRUNCATED)
358818334Speter	    l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0;
358918334Speter#endif
359018334Speter
359118334Speter	  if (h2 != 0 || l2 < 0 || l2 >= GET_MODE_BITSIZE (mode))
359218334Speter	    return 0;
359318334Speter
359418334Speter	  if (code == LSHIFTRT || code == ASHIFTRT)
359518334Speter	    rshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv,
359618334Speter			   code == ASHIFTRT);
359718334Speter	  else if (code == ASHIFT)
359818334Speter	    lshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 1);
359918334Speter	  else if (code == ROTATE)
360018334Speter	    lrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv);
360118334Speter	  else /* code == ROTATERT */
360218334Speter	    rrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv);
360318334Speter	  break;
360418334Speter
360518334Speter	default:
360618334Speter	  return 0;
360718334Speter	}
360818334Speter
360918334Speter      return immed_double_const (lv, hv, mode);
361018334Speter    }
361118334Speter
361218334Speter  if (GET_CODE (op0) != CONST_INT || GET_CODE (op1) != CONST_INT
361318334Speter      || width > HOST_BITS_PER_WIDE_INT || width == 0)
361418334Speter    {
361518334Speter      /* Even if we can't compute a constant result,
361618334Speter	 there are some cases worth simplifying.  */
361718334Speter
361818334Speter      switch (code)
361918334Speter	{
362018334Speter	case PLUS:
362118334Speter	  /* In IEEE floating point, x+0 is not the same as x.  Similarly
362218334Speter	     for the other optimizations below.  */
362318334Speter	  if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
362418334Speter	      && FLOAT_MODE_P (mode) && ! flag_fast_math)
362518334Speter	    break;
362618334Speter
362718334Speter	  if (op1 == CONST0_RTX (mode))
362818334Speter	    return op0;
362918334Speter
363018334Speter	  /* ((-a) + b) -> (b - a) and similarly for (a + (-b)) */
363118334Speter	  if (GET_CODE (op0) == NEG)
363218334Speter	    return cse_gen_binary (MINUS, mode, op1, XEXP (op0, 0));
363318334Speter	  else if (GET_CODE (op1) == NEG)
363418334Speter	    return cse_gen_binary (MINUS, mode, op0, XEXP (op1, 0));
363518334Speter
363618334Speter	  /* Handle both-operands-constant cases.  We can only add
363718334Speter	     CONST_INTs to constants since the sum of relocatable symbols
363818334Speter	     can't be handled by most assemblers.  Don't add CONST_INT
363918334Speter	     to CONST_INT since overflow won't be computed properly if wider
364018334Speter	     than HOST_BITS_PER_WIDE_INT.  */
364118334Speter
364218334Speter	  if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode
364318334Speter	      && GET_CODE (op1) == CONST_INT)
364418334Speter	    return plus_constant (op0, INTVAL (op1));
364518334Speter	  else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode
364618334Speter		   && GET_CODE (op0) == CONST_INT)
364718334Speter	    return plus_constant (op1, INTVAL (op0));
364818334Speter
364918334Speter	  /* See if this is something like X * C - X or vice versa or
365018334Speter	     if the multiplication is written as a shift.  If so, we can
365118334Speter	     distribute and make a new multiply, shift, or maybe just
365218334Speter	     have X (if C is 2 in the example above).  But don't make
365318334Speter	     real multiply if we didn't have one before.  */
365418334Speter
365518334Speter	  if (! FLOAT_MODE_P (mode))
365618334Speter	    {
365718334Speter	      HOST_WIDE_INT coeff0 = 1, coeff1 = 1;
365818334Speter	      rtx lhs = op0, rhs = op1;
365918334Speter	      int had_mult = 0;
366018334Speter
366118334Speter	      if (GET_CODE (lhs) == NEG)
366218334Speter		coeff0 = -1, lhs = XEXP (lhs, 0);
366318334Speter	      else if (GET_CODE (lhs) == MULT
366418334Speter		       && GET_CODE (XEXP (lhs, 1)) == CONST_INT)
366518334Speter		{
366618334Speter		  coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0);
366718334Speter		  had_mult = 1;
366818334Speter		}
366918334Speter	      else if (GET_CODE (lhs) == ASHIFT
367018334Speter		       && GET_CODE (XEXP (lhs, 1)) == CONST_INT
367118334Speter		       && INTVAL (XEXP (lhs, 1)) >= 0
367218334Speter		       && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
367318334Speter		{
367418334Speter		  coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
367518334Speter		  lhs = XEXP (lhs, 0);
367618334Speter		}
367718334Speter
367818334Speter	      if (GET_CODE (rhs) == NEG)
367918334Speter		coeff1 = -1, rhs = XEXP (rhs, 0);
368018334Speter	      else if (GET_CODE (rhs) == MULT
368118334Speter		       && GET_CODE (XEXP (rhs, 1)) == CONST_INT)
368218334Speter		{
368318334Speter		  coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0);
368418334Speter		  had_mult = 1;
368518334Speter		}
368618334Speter	      else if (GET_CODE (rhs) == ASHIFT
368718334Speter		       && GET_CODE (XEXP (rhs, 1)) == CONST_INT
368818334Speter		       && INTVAL (XEXP (rhs, 1)) >= 0
368918334Speter		       && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
369018334Speter		{
369118334Speter		  coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1));
369218334Speter		  rhs = XEXP (rhs, 0);
369318334Speter		}
369418334Speter
369518334Speter	      if (rtx_equal_p (lhs, rhs))
369618334Speter		{
369718334Speter		  tem = cse_gen_binary (MULT, mode, lhs,
369818334Speter					GEN_INT (coeff0 + coeff1));
369918334Speter		  return (GET_CODE (tem) == MULT && ! had_mult) ? 0 : tem;
370018334Speter		}
370118334Speter	    }
370218334Speter
370318334Speter	  /* If one of the operands is a PLUS or a MINUS, see if we can
370418334Speter	     simplify this by the associative law.
370518334Speter	     Don't use the associative law for floating point.
370618334Speter	     The inaccuracy makes it nonassociative,
370718334Speter	     and subtle programs can break if operations are associated.  */
370818334Speter
370918334Speter	  if (INTEGRAL_MODE_P (mode)
371018334Speter	      && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
371118334Speter		  || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS)
371218334Speter	      && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
371318334Speter	    return tem;
371418334Speter	  break;
371518334Speter
371618334Speter	case COMPARE:
371718334Speter#ifdef HAVE_cc0
371818334Speter	  /* Convert (compare FOO (const_int 0)) to FOO unless we aren't
371918334Speter	     using cc0, in which case we want to leave it as a COMPARE
372018334Speter	     so we can distinguish it from a register-register-copy.
372118334Speter
372218334Speter	     In IEEE floating point, x-0 is not the same as x.  */
372318334Speter
372418334Speter	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
372518334Speter	       || ! FLOAT_MODE_P (mode) || flag_fast_math)
372618334Speter	      && op1 == CONST0_RTX (mode))
372718334Speter	    return op0;
372818334Speter#else
372918334Speter	  /* Do nothing here.  */
373018334Speter#endif
373118334Speter	  break;
373218334Speter
373318334Speter	case MINUS:
373418334Speter	  /* None of these optimizations can be done for IEEE
373518334Speter	     floating point.  */
373618334Speter	  if (TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
373718334Speter	      && FLOAT_MODE_P (mode) && ! flag_fast_math)
373818334Speter	    break;
373918334Speter
374018334Speter	  /* We can't assume x-x is 0 even with non-IEEE floating point,
374118334Speter	     but since it is zero except in very strange circumstances, we
374218334Speter	     will treat it as zero with -ffast-math.  */
374318334Speter	  if (rtx_equal_p (op0, op1)
374418334Speter	      && ! side_effects_p (op0)
374518334Speter	      && (! FLOAT_MODE_P (mode) || flag_fast_math))
374618334Speter	    return CONST0_RTX (mode);
374718334Speter
374818334Speter	  /* Change subtraction from zero into negation.  */
374918334Speter	  if (op0 == CONST0_RTX (mode))
375018334Speter	    return gen_rtx (NEG, mode, op1);
375118334Speter
375218334Speter	  /* (-1 - a) is ~a.  */
375318334Speter	  if (op0 == constm1_rtx)
375418334Speter	    return gen_rtx (NOT, mode, op1);
375518334Speter
375618334Speter	  /* Subtracting 0 has no effect.  */
375718334Speter	  if (op1 == CONST0_RTX (mode))
375818334Speter	    return op0;
375918334Speter
376018334Speter	  /* See if this is something like X * C - X or vice versa or
376118334Speter	     if the multiplication is written as a shift.  If so, we can
376218334Speter	     distribute and make a new multiply, shift, or maybe just
376318334Speter	     have X (if C is 2 in the example above).  But don't make
376418334Speter	     real multiply if we didn't have one before.  */
376518334Speter
376618334Speter	  if (! FLOAT_MODE_P (mode))
376718334Speter	    {
376818334Speter	      HOST_WIDE_INT coeff0 = 1, coeff1 = 1;
376918334Speter	      rtx lhs = op0, rhs = op1;
377018334Speter	      int had_mult = 0;
377118334Speter
377218334Speter	      if (GET_CODE (lhs) == NEG)
377318334Speter		coeff0 = -1, lhs = XEXP (lhs, 0);
377418334Speter	      else if (GET_CODE (lhs) == MULT
377518334Speter		       && GET_CODE (XEXP (lhs, 1)) == CONST_INT)
377618334Speter		{
377718334Speter		  coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0);
377818334Speter		  had_mult = 1;
377918334Speter		}
378018334Speter	      else if (GET_CODE (lhs) == ASHIFT
378118334Speter		       && GET_CODE (XEXP (lhs, 1)) == CONST_INT
378218334Speter		       && INTVAL (XEXP (lhs, 1)) >= 0
378318334Speter		       && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
378418334Speter		{
378518334Speter		  coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
378618334Speter		  lhs = XEXP (lhs, 0);
378718334Speter		}
378818334Speter
378918334Speter	      if (GET_CODE (rhs) == NEG)
379018334Speter		coeff1 = - 1, rhs = XEXP (rhs, 0);
379118334Speter	      else if (GET_CODE (rhs) == MULT
379218334Speter		       && GET_CODE (XEXP (rhs, 1)) == CONST_INT)
379318334Speter		{
379418334Speter		  coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0);
379518334Speter		  had_mult = 1;
379618334Speter		}
379718334Speter	      else if (GET_CODE (rhs) == ASHIFT
379818334Speter		       && GET_CODE (XEXP (rhs, 1)) == CONST_INT
379918334Speter		       && INTVAL (XEXP (rhs, 1)) >= 0
380018334Speter		       && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
380118334Speter		{
380218334Speter		  coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1));
380318334Speter		  rhs = XEXP (rhs, 0);
380418334Speter		}
380518334Speter
380618334Speter	      if (rtx_equal_p (lhs, rhs))
380718334Speter		{
380818334Speter		  tem = cse_gen_binary (MULT, mode, lhs,
380918334Speter					GEN_INT (coeff0 - coeff1));
381018334Speter		  return (GET_CODE (tem) == MULT && ! had_mult) ? 0 : tem;
381118334Speter		}
381218334Speter	    }
381318334Speter
381418334Speter	  /* (a - (-b)) -> (a + b).  */
381518334Speter	  if (GET_CODE (op1) == NEG)
381618334Speter	    return cse_gen_binary (PLUS, mode, op0, XEXP (op1, 0));
381718334Speter
381818334Speter	  /* If one of the operands is a PLUS or a MINUS, see if we can
381918334Speter	     simplify this by the associative law.
382018334Speter	     Don't use the associative law for floating point.
382118334Speter	     The inaccuracy makes it nonassociative,
382218334Speter	     and subtle programs can break if operations are associated.  */
382318334Speter
382418334Speter	  if (INTEGRAL_MODE_P (mode)
382518334Speter	      && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
382618334Speter		  || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS)
382718334Speter	      && (tem = simplify_plus_minus (code, mode, op0, op1)) != 0)
382818334Speter	    return tem;
382918334Speter
383018334Speter	  /* Don't let a relocatable value get a negative coeff.  */
383118334Speter	  if (GET_CODE (op1) == CONST_INT && GET_MODE (op0) != VOIDmode)
383218334Speter	    return plus_constant (op0, - INTVAL (op1));
383318334Speter
383418334Speter	  /* (x - (x & y)) -> (x & ~y) */
383518334Speter	  if (GET_CODE (op1) == AND)
383618334Speter	    {
383718334Speter	     if (rtx_equal_p (op0, XEXP (op1, 0)))
383818334Speter	       return cse_gen_binary (AND, mode, op0, gen_rtx (NOT, mode, XEXP (op1, 1)));
383918334Speter	     if (rtx_equal_p (op0, XEXP (op1, 1)))
384018334Speter	       return cse_gen_binary (AND, mode, op0, gen_rtx (NOT, mode, XEXP (op1, 0)));
384118334Speter	   }
384218334Speter	  break;
384318334Speter
384418334Speter	case MULT:
384518334Speter	  if (op1 == constm1_rtx)
384618334Speter	    {
384718334Speter	      tem = simplify_unary_operation (NEG, mode, op0, mode);
384818334Speter
384918334Speter	      return tem ? tem : gen_rtx (NEG, mode, op0);
385018334Speter	    }
385118334Speter
385218334Speter	  /* In IEEE floating point, x*0 is not always 0.  */
385318334Speter	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
385418334Speter	       || ! FLOAT_MODE_P (mode) || flag_fast_math)
385518334Speter	      && op1 == CONST0_RTX (mode)
385618334Speter	      && ! side_effects_p (op0))
385718334Speter	    return op1;
385818334Speter
385918334Speter	  /* In IEEE floating point, x*1 is not equivalent to x for nans.
386018334Speter	     However, ANSI says we can drop signals,
386118334Speter	     so we can do this anyway.  */
386218334Speter	  if (op1 == CONST1_RTX (mode))
386318334Speter	    return op0;
386418334Speter
386518334Speter	  /* Convert multiply by constant power of two into shift unless
386618334Speter	     we are still generating RTL.  This test is a kludge.  */
386718334Speter	  if (GET_CODE (op1) == CONST_INT
386818334Speter	      && (val = exact_log2 (INTVAL (op1))) >= 0
386918334Speter	      && ! rtx_equal_function_value_matters)
387018334Speter	    return gen_rtx (ASHIFT, mode, op0, GEN_INT (val));
387118334Speter
387218334Speter	  if (GET_CODE (op1) == CONST_DOUBLE
387318334Speter	      && GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT)
387418334Speter	    {
387518334Speter	      REAL_VALUE_TYPE d;
387618334Speter	      jmp_buf handler;
387718334Speter	      int op1is2, op1ism1;
387818334Speter
387918334Speter	      if (setjmp (handler))
388018334Speter		return 0;
388118334Speter
388218334Speter	      set_float_handler (handler);
388318334Speter	      REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
388418334Speter	      op1is2 = REAL_VALUES_EQUAL (d, dconst2);
388518334Speter	      op1ism1 = REAL_VALUES_EQUAL (d, dconstm1);
388618334Speter	      set_float_handler (NULL_PTR);
388718334Speter
388818334Speter	      /* x*2 is x+x and x*(-1) is -x */
388918334Speter	      if (op1is2 && GET_MODE (op0) == mode)
389018334Speter		return gen_rtx (PLUS, mode, op0, copy_rtx (op0));
389118334Speter
389218334Speter	      else if (op1ism1 && GET_MODE (op0) == mode)
389318334Speter		return gen_rtx (NEG, mode, op0);
389418334Speter	    }
389518334Speter	  break;
389618334Speter
389718334Speter	case IOR:
389818334Speter	  if (op1 == const0_rtx)
389918334Speter	    return op0;
390018334Speter	  if (GET_CODE (op1) == CONST_INT
390118334Speter	      && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
390218334Speter	    return op1;
390318334Speter	  if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
390418334Speter	    return op0;
390518334Speter	  /* A | (~A) -> -1 */
390618334Speter	  if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
390718334Speter	       || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
390818334Speter	      && ! side_effects_p (op0)
390918334Speter	      && GET_MODE_CLASS (mode) != MODE_CC)
391018334Speter	    return constm1_rtx;
391118334Speter	  break;
391218334Speter
391318334Speter	case XOR:
391418334Speter	  if (op1 == const0_rtx)
391518334Speter	    return op0;
391618334Speter	  if (GET_CODE (op1) == CONST_INT
391718334Speter	      && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
391818334Speter	    return gen_rtx (NOT, mode, op0);
391918334Speter	  if (op0 == op1 && ! side_effects_p (op0)
392018334Speter	      && GET_MODE_CLASS (mode) != MODE_CC)
392118334Speter	    return const0_rtx;
392218334Speter	  break;
392318334Speter
392418334Speter	case AND:
392518334Speter	  if (op1 == const0_rtx && ! side_effects_p (op0))
392618334Speter	    return const0_rtx;
392718334Speter	  if (GET_CODE (op1) == CONST_INT
392818334Speter	      && (INTVAL (op1) & GET_MODE_MASK (mode)) == GET_MODE_MASK (mode))
392918334Speter	    return op0;
393018334Speter	  if (op0 == op1 && ! side_effects_p (op0)
393118334Speter	      && GET_MODE_CLASS (mode) != MODE_CC)
393218334Speter	    return op0;
393318334Speter	  /* A & (~A) -> 0 */
393418334Speter	  if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
393518334Speter	       || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
393618334Speter	      && ! side_effects_p (op0)
393718334Speter	      && GET_MODE_CLASS (mode) != MODE_CC)
393818334Speter	    return const0_rtx;
393918334Speter	  break;
394018334Speter
394118334Speter	case UDIV:
394218334Speter	  /* Convert divide by power of two into shift (divide by 1 handled
394318334Speter	     below).  */
394418334Speter	  if (GET_CODE (op1) == CONST_INT
394518334Speter	      && (arg1 = exact_log2 (INTVAL (op1))) > 0)
394618334Speter	    return gen_rtx (LSHIFTRT, mode, op0, GEN_INT (arg1));
394718334Speter
394818334Speter	  /* ... fall through ... */
394918334Speter
395018334Speter	case DIV:
395118334Speter	  if (op1 == CONST1_RTX (mode))
395218334Speter	    return op0;
395318334Speter
395418334Speter	  /* In IEEE floating point, 0/x is not always 0.  */
395518334Speter	  if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
395618334Speter	       || ! FLOAT_MODE_P (mode) || flag_fast_math)
395718334Speter	      && op0 == CONST0_RTX (mode)
395818334Speter	      && ! side_effects_p (op1))
395918334Speter	    return op0;
396018334Speter
396118334Speter#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
396218334Speter	  /* Change division by a constant into multiplication.  Only do
396318334Speter	     this with -ffast-math until an expert says it is safe in
396418334Speter	     general.  */
396518334Speter	  else if (GET_CODE (op1) == CONST_DOUBLE
396618334Speter		   && GET_MODE_CLASS (GET_MODE (op1)) == MODE_FLOAT
396718334Speter		   && op1 != CONST0_RTX (mode)
396818334Speter		   && flag_fast_math)
396918334Speter	    {
397018334Speter	      REAL_VALUE_TYPE d;
397118334Speter	      REAL_VALUE_FROM_CONST_DOUBLE (d, op1);
397218334Speter
397318334Speter	      if (! REAL_VALUES_EQUAL (d, dconst0))
397418334Speter		{
397518334Speter#if defined (REAL_ARITHMETIC)
397618334Speter		  REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d);
397718334Speter		  return gen_rtx (MULT, mode, op0,
397818334Speter				  CONST_DOUBLE_FROM_REAL_VALUE (d, mode));
397918334Speter#else
398018334Speter		  return gen_rtx (MULT, mode, op0,
398118334Speter				  CONST_DOUBLE_FROM_REAL_VALUE (1./d, mode));
398218334Speter#endif
398318334Speter		}
398418334Speter	    }
398518334Speter#endif
398618334Speter	  break;
398718334Speter
398818334Speter	case UMOD:
398918334Speter	  /* Handle modulus by power of two (mod with 1 handled below).  */
399018334Speter	  if (GET_CODE (op1) == CONST_INT
399118334Speter	      && exact_log2 (INTVAL (op1)) > 0)
399218334Speter	    return gen_rtx (AND, mode, op0, GEN_INT (INTVAL (op1) - 1));
399318334Speter
399418334Speter	  /* ... fall through ... */
399518334Speter
399618334Speter	case MOD:
399718334Speter	  if ((op0 == const0_rtx || op1 == const1_rtx)
399818334Speter	      && ! side_effects_p (op0) && ! side_effects_p (op1))
399918334Speter	    return const0_rtx;
400018334Speter	  break;
400118334Speter
400218334Speter	case ROTATERT:
400318334Speter	case ROTATE:
400418334Speter	  /* Rotating ~0 always results in ~0.  */
400518334Speter	  if (GET_CODE (op0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT
400618334Speter	      && INTVAL (op0) == GET_MODE_MASK (mode)
400718334Speter	      && ! side_effects_p (op1))
400818334Speter	    return op0;
400918334Speter
401018334Speter	  /* ... fall through ... */
401118334Speter
401218334Speter	case ASHIFT:
401318334Speter	case ASHIFTRT:
401418334Speter	case LSHIFTRT:
401518334Speter	  if (op1 == const0_rtx)
401618334Speter	    return op0;
401718334Speter	  if (op0 == const0_rtx && ! side_effects_p (op1))
401818334Speter	    return op0;
401918334Speter	  break;
402018334Speter
402118334Speter	case SMIN:
402218334Speter	  if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT
402318334Speter	      && INTVAL (op1) == (HOST_WIDE_INT) 1 << (width -1)
402418334Speter	      && ! side_effects_p (op0))
402518334Speter	    return op1;
402618334Speter	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
402718334Speter	    return op0;
402818334Speter	  break;
402918334Speter
403018334Speter	case SMAX:
403118334Speter	  if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (op1) == CONST_INT
403218334Speter	      && (INTVAL (op1)
403318334Speter		  == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
403418334Speter	      && ! side_effects_p (op0))
403518334Speter	    return op1;
403618334Speter	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
403718334Speter	    return op0;
403818334Speter	  break;
403918334Speter
404018334Speter	case UMIN:
404118334Speter	  if (op1 == const0_rtx && ! side_effects_p (op0))
404218334Speter	    return op1;
404318334Speter	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
404418334Speter	    return op0;
404518334Speter	  break;
404618334Speter
404718334Speter	case UMAX:
404818334Speter	  if (op1 == constm1_rtx && ! side_effects_p (op0))
404918334Speter	    return op1;
405018334Speter	  else if (rtx_equal_p (op0, op1) && ! side_effects_p (op0))
405118334Speter	    return op0;
405218334Speter	  break;
405318334Speter
405418334Speter	default:
405518334Speter	  abort ();
405618334Speter	}
405718334Speter
405818334Speter      return 0;
405918334Speter    }
406018334Speter
406118334Speter  /* Get the integer argument values in two forms:
406218334Speter     zero-extended in ARG0, ARG1 and sign-extended in ARG0S, ARG1S.  */
406318334Speter
406418334Speter  arg0 = INTVAL (op0);
406518334Speter  arg1 = INTVAL (op1);
406618334Speter
406718334Speter  if (width < HOST_BITS_PER_WIDE_INT)
406818334Speter    {
406918334Speter      arg0 &= ((HOST_WIDE_INT) 1 << width) - 1;
407018334Speter      arg1 &= ((HOST_WIDE_INT) 1 << width) - 1;
407118334Speter
407218334Speter      arg0s = arg0;
407318334Speter      if (arg0s & ((HOST_WIDE_INT) 1 << (width - 1)))
407418334Speter	arg0s |= ((HOST_WIDE_INT) (-1) << width);
407518334Speter
407618334Speter      arg1s = arg1;
407718334Speter      if (arg1s & ((HOST_WIDE_INT) 1 << (width - 1)))
407818334Speter	arg1s |= ((HOST_WIDE_INT) (-1) << width);
407918334Speter    }
408018334Speter  else
408118334Speter    {
408218334Speter      arg0s = arg0;
408318334Speter      arg1s = arg1;
408418334Speter    }
408518334Speter
408618334Speter  /* Compute the value of the arithmetic.  */
408718334Speter
408818334Speter  switch (code)
408918334Speter    {
409018334Speter    case PLUS:
409118334Speter      val = arg0s + arg1s;
409218334Speter      break;
409318334Speter
409418334Speter    case MINUS:
409518334Speter      val = arg0s - arg1s;
409618334Speter      break;
409718334Speter
409818334Speter    case MULT:
409918334Speter      val = arg0s * arg1s;
410018334Speter      break;
410118334Speter
410218334Speter    case DIV:
410318334Speter      if (arg1s == 0)
410418334Speter	return 0;
410518334Speter      val = arg0s / arg1s;
410618334Speter      break;
410718334Speter
410818334Speter    case MOD:
410918334Speter      if (arg1s == 0)
411018334Speter	return 0;
411118334Speter      val = arg0s % arg1s;
411218334Speter      break;
411318334Speter
411418334Speter    case UDIV:
411518334Speter      if (arg1 == 0)
411618334Speter	return 0;
411718334Speter      val = (unsigned HOST_WIDE_INT) arg0 / arg1;
411818334Speter      break;
411918334Speter
412018334Speter    case UMOD:
412118334Speter      if (arg1 == 0)
412218334Speter	return 0;
412318334Speter      val = (unsigned HOST_WIDE_INT) arg0 % arg1;
412418334Speter      break;
412518334Speter
412618334Speter    case AND:
412718334Speter      val = arg0 & arg1;
412818334Speter      break;
412918334Speter
413018334Speter    case IOR:
413118334Speter      val = arg0 | arg1;
413218334Speter      break;
413318334Speter
413418334Speter    case XOR:
413518334Speter      val = arg0 ^ arg1;
413618334Speter      break;
413718334Speter
413818334Speter    case LSHIFTRT:
413918334Speter      /* If shift count is undefined, don't fold it; let the machine do
414018334Speter	 what it wants.  But truncate it if the machine will do that.  */
414118334Speter      if (arg1 < 0)
414218334Speter	return 0;
414318334Speter
414418334Speter#ifdef SHIFT_COUNT_TRUNCATED
414518334Speter      if (SHIFT_COUNT_TRUNCATED)
414618334Speter	arg1 %= width;
414718334Speter#endif
414818334Speter
414918334Speter      val = ((unsigned HOST_WIDE_INT) arg0) >> arg1;
415018334Speter      break;
415118334Speter
415218334Speter    case ASHIFT:
415318334Speter      if (arg1 < 0)
415418334Speter	return 0;
415518334Speter
415618334Speter#ifdef SHIFT_COUNT_TRUNCATED
415718334Speter      if (SHIFT_COUNT_TRUNCATED)
415818334Speter	arg1 %= width;
415918334Speter#endif
416018334Speter
416118334Speter      val = ((unsigned HOST_WIDE_INT) arg0) << arg1;
416218334Speter      break;
416318334Speter
416418334Speter    case ASHIFTRT:
416518334Speter      if (arg1 < 0)
416618334Speter	return 0;
416718334Speter
416818334Speter#ifdef SHIFT_COUNT_TRUNCATED
416918334Speter      if (SHIFT_COUNT_TRUNCATED)
417018334Speter	arg1 %= width;
417118334Speter#endif
417218334Speter
417318334Speter      val = arg0s >> arg1;
417418334Speter
417518334Speter      /* Bootstrap compiler may not have sign extended the right shift.
417618334Speter	 Manually extend the sign to insure bootstrap cc matches gcc.  */
417718334Speter      if (arg0s < 0 && arg1 > 0)
417818334Speter	val |= ((HOST_WIDE_INT) -1) << (HOST_BITS_PER_WIDE_INT - arg1);
417918334Speter
418018334Speter      break;
418118334Speter
418218334Speter    case ROTATERT:
418318334Speter      if (arg1 < 0)
418418334Speter	return 0;
418518334Speter
418618334Speter      arg1 %= width;
418718334Speter      val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1))
418818334Speter	     | (((unsigned HOST_WIDE_INT) arg0) >> arg1));
418918334Speter      break;
419018334Speter
419118334Speter    case ROTATE:
419218334Speter      if (arg1 < 0)
419318334Speter	return 0;
419418334Speter
419518334Speter      arg1 %= width;
419618334Speter      val = ((((unsigned HOST_WIDE_INT) arg0) << arg1)
419718334Speter	     | (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1)));
419818334Speter      break;
419918334Speter
420018334Speter    case COMPARE:
420118334Speter      /* Do nothing here.  */
420218334Speter      return 0;
420318334Speter
420418334Speter    case SMIN:
420518334Speter      val = arg0s <= arg1s ? arg0s : arg1s;
420618334Speter      break;
420718334Speter
420818334Speter    case UMIN:
420918334Speter      val = ((unsigned HOST_WIDE_INT) arg0
421018334Speter	     <= (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1);
421118334Speter      break;
421218334Speter
421318334Speter    case SMAX:
421418334Speter      val = arg0s > arg1s ? arg0s : arg1s;
421518334Speter      break;
421618334Speter
421718334Speter    case UMAX:
421818334Speter      val = ((unsigned HOST_WIDE_INT) arg0
421918334Speter	     > (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1);
422018334Speter      break;
422118334Speter
422218334Speter    default:
422318334Speter      abort ();
422418334Speter    }
422518334Speter
422618334Speter  /* Clear the bits that don't belong in our mode, unless they and our sign
422718334Speter     bit are all one.  So we get either a reasonable negative value or a
422818334Speter     reasonable unsigned value for this mode.  */
422918334Speter  if (width < HOST_BITS_PER_WIDE_INT
423018334Speter      && ((val & ((HOST_WIDE_INT) (-1) << (width - 1)))
423118334Speter	  != ((HOST_WIDE_INT) (-1) << (width - 1))))
423218334Speter    val &= ((HOST_WIDE_INT) 1 << width) - 1;
423318334Speter
423418334Speter  /* If this would be an entire word for the target, but is not for
423518334Speter     the host, then sign-extend on the host so that the number will look
423618334Speter     the same way on the host that it would on the target.
423718334Speter
423818334Speter     For example, when building a 64 bit alpha hosted 32 bit sparc
423918334Speter     targeted compiler, then we want the 32 bit unsigned value -1 to be
424018334Speter     represented as a 64 bit value -1, and not as 0x00000000ffffffff.
424118334Speter     The later confuses the sparc backend.  */
424218334Speter
424318334Speter  if (BITS_PER_WORD < HOST_BITS_PER_WIDE_INT && BITS_PER_WORD == width
424418334Speter      && (val & ((HOST_WIDE_INT) 1 << (width - 1))))
424518334Speter    val |= ((HOST_WIDE_INT) (-1) << width);
424618334Speter
424718334Speter  return GEN_INT (val);
424818334Speter}
424918334Speter
425018334Speter/* Simplify a PLUS or MINUS, at least one of whose operands may be another
425118334Speter   PLUS or MINUS.
425218334Speter
425318334Speter   Rather than test for specific case, we do this by a brute-force method
425418334Speter   and do all possible simplifications until no more changes occur.  Then
425518334Speter   we rebuild the operation.  */
425618334Speter
425718334Speterstatic rtx
425818334Spetersimplify_plus_minus (code, mode, op0, op1)
425918334Speter     enum rtx_code code;
426018334Speter     enum machine_mode mode;
426118334Speter     rtx op0, op1;
426218334Speter{
426318334Speter  rtx ops[8];
426418334Speter  int negs[8];
426518334Speter  rtx result, tem;
426618334Speter  int n_ops = 2, input_ops = 2, input_consts = 0, n_consts = 0;
426718334Speter  int first = 1, negate = 0, changed;
426818334Speter  int i, j;
426918334Speter
427018334Speter  bzero ((char *) ops, sizeof ops);
427118334Speter
427218334Speter  /* Set up the two operands and then expand them until nothing has been
427318334Speter     changed.  If we run out of room in our array, give up; this should
427418334Speter     almost never happen.  */
427518334Speter
427618334Speter  ops[0] = op0, ops[1] = op1, negs[0] = 0, negs[1] = (code == MINUS);
427718334Speter
427818334Speter  changed = 1;
427918334Speter  while (changed)
428018334Speter    {
428118334Speter      changed = 0;
428218334Speter
428318334Speter      for (i = 0; i < n_ops; i++)
428418334Speter	switch (GET_CODE (ops[i]))
428518334Speter	  {
428618334Speter	  case PLUS:
428718334Speter	  case MINUS:
428818334Speter	    if (n_ops == 7)
428918334Speter	      return 0;
429018334Speter
429118334Speter	    ops[n_ops] = XEXP (ops[i], 1);
429218334Speter	    negs[n_ops++] = GET_CODE (ops[i]) == MINUS ? !negs[i] : negs[i];
429318334Speter	    ops[i] = XEXP (ops[i], 0);
429418334Speter	    input_ops++;
429518334Speter	    changed = 1;
429618334Speter	    break;
429718334Speter
429818334Speter	  case NEG:
429918334Speter	    ops[i] = XEXP (ops[i], 0);
430018334Speter	    negs[i] = ! negs[i];
430118334Speter	    changed = 1;
430218334Speter	    break;
430318334Speter
430418334Speter	  case CONST:
430518334Speter	    ops[i] = XEXP (ops[i], 0);
430618334Speter	    input_consts++;
430718334Speter	    changed = 1;
430818334Speter	    break;
430918334Speter
431018334Speter	  case NOT:
431118334Speter	    /* ~a -> (-a - 1) */
431218334Speter	    if (n_ops != 7)
431318334Speter	      {
431418334Speter		ops[n_ops] = constm1_rtx;
431518334Speter		negs[n_ops++] = negs[i];
431618334Speter		ops[i] = XEXP (ops[i], 0);
431718334Speter		negs[i] = ! negs[i];
431818334Speter		changed = 1;
431918334Speter	      }
432018334Speter	    break;
432118334Speter
432218334Speter	  case CONST_INT:
432318334Speter	    if (negs[i])
432418334Speter	      ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0, changed = 1;
432518334Speter	    break;
432618334Speter	  }
432718334Speter    }
432818334Speter
432918334Speter  /* If we only have two operands, we can't do anything.  */
433018334Speter  if (n_ops <= 2)
433118334Speter    return 0;
433218334Speter
433318334Speter  /* Now simplify each pair of operands until nothing changes.  The first
433418334Speter     time through just simplify constants against each other.  */
433518334Speter
433618334Speter  changed = 1;
433718334Speter  while (changed)
433818334Speter    {
433918334Speter      changed = first;
434018334Speter
434118334Speter      for (i = 0; i < n_ops - 1; i++)
434218334Speter	for (j = i + 1; j < n_ops; j++)
434318334Speter	  if (ops[i] != 0 && ops[j] != 0
434418334Speter	      && (! first || (CONSTANT_P (ops[i]) && CONSTANT_P (ops[j]))))
434518334Speter	    {
434618334Speter	      rtx lhs = ops[i], rhs = ops[j];
434718334Speter	      enum rtx_code ncode = PLUS;
434818334Speter
434918334Speter	      if (negs[i] && ! negs[j])
435018334Speter		lhs = ops[j], rhs = ops[i], ncode = MINUS;
435118334Speter	      else if (! negs[i] && negs[j])
435218334Speter		ncode = MINUS;
435318334Speter
435418334Speter	      tem = simplify_binary_operation (ncode, mode, lhs, rhs);
435518334Speter	      if (tem)
435618334Speter		{
435718334Speter		  ops[i] = tem, ops[j] = 0;
435818334Speter		  negs[i] = negs[i] && negs[j];
435918334Speter		  if (GET_CODE (tem) == NEG)
436018334Speter		    ops[i] = XEXP (tem, 0), negs[i] = ! negs[i];
436118334Speter
436218334Speter		  if (GET_CODE (ops[i]) == CONST_INT && negs[i])
436318334Speter		    ops[i] = GEN_INT (- INTVAL (ops[i])), negs[i] = 0;
436418334Speter		  changed = 1;
436518334Speter		}
436618334Speter	    }
436718334Speter
436818334Speter      first = 0;
436918334Speter    }
437018334Speter
437118334Speter  /* Pack all the operands to the lower-numbered entries and give up if
437218334Speter     we didn't reduce the number of operands we had.  Make sure we
437318334Speter     count a CONST as two operands.  If we have the same number of
437418334Speter     operands, but have made more CONSTs than we had, this is also
437518334Speter     an improvement, so accept it.  */
437618334Speter
437718334Speter  for (i = 0, j = 0; j < n_ops; j++)
437818334Speter    if (ops[j] != 0)
437918334Speter      {
438018334Speter	ops[i] = ops[j], negs[i++] = negs[j];
438118334Speter	if (GET_CODE (ops[j]) == CONST)
438218334Speter	  n_consts++;
438318334Speter      }
438418334Speter
438518334Speter  if (i + n_consts > input_ops
438618334Speter      || (i + n_consts == input_ops && n_consts <= input_consts))
438718334Speter    return 0;
438818334Speter
438918334Speter  n_ops = i;
439018334Speter
439118334Speter  /* If we have a CONST_INT, put it last.  */
439218334Speter  for (i = 0; i < n_ops - 1; i++)
439318334Speter    if (GET_CODE (ops[i]) == CONST_INT)
439418334Speter      {
439518334Speter	tem = ops[n_ops - 1], ops[n_ops - 1] = ops[i] , ops[i] = tem;
439618334Speter	j = negs[n_ops - 1], negs[n_ops - 1] = negs[i], negs[i] = j;
439718334Speter      }
439818334Speter
439918334Speter  /* Put a non-negated operand first.  If there aren't any, make all
440018334Speter     operands positive and negate the whole thing later.  */
440118334Speter  for (i = 0; i < n_ops && negs[i]; i++)
440218334Speter    ;
440318334Speter
440418334Speter  if (i == n_ops)
440518334Speter    {
440618334Speter      for (i = 0; i < n_ops; i++)
440718334Speter	negs[i] = 0;
440818334Speter      negate = 1;
440918334Speter    }
441018334Speter  else if (i != 0)
441118334Speter    {
441218334Speter      tem = ops[0], ops[0] = ops[i], ops[i] = tem;
441318334Speter      j = negs[0], negs[0] = negs[i], negs[i] = j;
441418334Speter    }
441518334Speter
441618334Speter  /* Now make the result by performing the requested operations.  */
441718334Speter  result = ops[0];
441818334Speter  for (i = 1; i < n_ops; i++)
441918334Speter    result = cse_gen_binary (negs[i] ? MINUS : PLUS, mode, result, ops[i]);
442018334Speter
442118334Speter  return negate ? gen_rtx (NEG, mode, result) : result;
442218334Speter}
442318334Speter
442418334Speter/* Make a binary operation by properly ordering the operands and
442518334Speter   seeing if the expression folds.  */
442618334Speter
442718334Speterstatic rtx
442818334Spetercse_gen_binary (code, mode, op0, op1)
442918334Speter     enum rtx_code code;
443018334Speter     enum machine_mode mode;
443118334Speter     rtx op0, op1;
443218334Speter{
443318334Speter  rtx tem;
443418334Speter
443518334Speter  /* Put complex operands first and constants second if commutative.  */
443618334Speter  if (GET_RTX_CLASS (code) == 'c'
443718334Speter      && ((CONSTANT_P (op0) && GET_CODE (op1) != CONST_INT)
443818334Speter	  || (GET_RTX_CLASS (GET_CODE (op0)) == 'o'
443918334Speter	      && GET_RTX_CLASS (GET_CODE (op1)) != 'o')
444018334Speter	  || (GET_CODE (op0) == SUBREG
444118334Speter	      && GET_RTX_CLASS (GET_CODE (SUBREG_REG (op0))) == 'o'
444218334Speter	      && GET_RTX_CLASS (GET_CODE (op1)) != 'o')))
444318334Speter    tem = op0, op0 = op1, op1 = tem;
444418334Speter
444518334Speter  /* If this simplifies, do it.  */
444618334Speter  tem = simplify_binary_operation (code, mode, op0, op1);
444718334Speter
444818334Speter  if (tem)
444918334Speter    return tem;
445018334Speter
445118334Speter  /* Handle addition and subtraction of CONST_INT specially.  Otherwise,
445218334Speter     just form the operation.  */
445318334Speter
445418334Speter  if (code == PLUS && GET_CODE (op1) == CONST_INT
445518334Speter      && GET_MODE (op0) != VOIDmode)
445618334Speter    return plus_constant (op0, INTVAL (op1));
445718334Speter  else if (code == MINUS && GET_CODE (op1) == CONST_INT
445818334Speter	   && GET_MODE (op0) != VOIDmode)
445918334Speter    return plus_constant (op0, - INTVAL (op1));
446018334Speter  else
446118334Speter    return gen_rtx (code, mode, op0, op1);
446218334Speter}
446318334Speter
446418334Speter/* Like simplify_binary_operation except used for relational operators.
446518334Speter   MODE is the mode of the operands, not that of the result.  If MODE
446618334Speter   is VOIDmode, both operands must also be VOIDmode and we compare the
446718334Speter   operands in "infinite precision".
446818334Speter
446918334Speter   If no simplification is possible, this function returns zero.  Otherwise,
447018334Speter   it returns either const_true_rtx or const0_rtx.  */
447118334Speter
447218334Speterrtx
447318334Spetersimplify_relational_operation (code, mode, op0, op1)
447418334Speter     enum rtx_code code;
447518334Speter     enum machine_mode mode;
447618334Speter     rtx op0, op1;
447718334Speter{
447818334Speter  int equal, op0lt, op0ltu, op1lt, op1ltu;
447918334Speter  rtx tem;
448018334Speter
448118334Speter  /* If op0 is a compare, extract the comparison arguments from it.  */
448218334Speter  if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
448318334Speter    op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
448418334Speter
448518334Speter  /* We can't simplify MODE_CC values since we don't know what the
448618334Speter     actual comparison is.  */
448718334Speter  if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC
448818334Speter#ifdef HAVE_cc0
448918334Speter      || op0 == cc0_rtx
449018334Speter#endif
449118334Speter      )
449218334Speter    return 0;
449318334Speter
449418334Speter  /* For integer comparisons of A and B maybe we can simplify A - B and can
449518334Speter     then simplify a comparison of that with zero.  If A and B are both either
449618334Speter     a register or a CONST_INT, this can't help; testing for these cases will
449718334Speter     prevent infinite recursion here and speed things up.
449818334Speter
449918334Speter     If CODE is an unsigned comparison, then we can never do this optimization,
450018334Speter     because it gives an incorrect result if the subtraction wraps around zero.
450118334Speter     ANSI C defines unsigned operations such that they never overflow, and
450218334Speter     thus such cases can not be ignored.  */
450318334Speter
450418334Speter  if (INTEGRAL_MODE_P (mode) && op1 != const0_rtx
450518334Speter      && ! ((GET_CODE (op0) == REG || GET_CODE (op0) == CONST_INT)
450618334Speter	    && (GET_CODE (op1) == REG || GET_CODE (op1) == CONST_INT))
450718334Speter      && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
450818334Speter      && code != GTU && code != GEU && code != LTU && code != LEU)
450918334Speter    return simplify_relational_operation (signed_condition (code),
451018334Speter					  mode, tem, const0_rtx);
451118334Speter
451218334Speter  /* For non-IEEE floating-point, if the two operands are equal, we know the
451318334Speter     result.  */
451418334Speter  if (rtx_equal_p (op0, op1)
451518334Speter      && (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
451618334Speter	  || ! FLOAT_MODE_P (GET_MODE (op0)) || flag_fast_math))
451718334Speter    equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
451818334Speter
451918334Speter  /* If the operands are floating-point constants, see if we can fold
452018334Speter     the result.  */
452118334Speter#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
452218334Speter  else if (GET_CODE (op0) == CONST_DOUBLE && GET_CODE (op1) == CONST_DOUBLE
452318334Speter	   && GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
452418334Speter    {
452518334Speter      REAL_VALUE_TYPE d0, d1;
452618334Speter      jmp_buf handler;
452718334Speter
452818334Speter      if (setjmp (handler))
452918334Speter	return 0;
453018334Speter
453118334Speter      set_float_handler (handler);
453218334Speter      REAL_VALUE_FROM_CONST_DOUBLE (d0, op0);
453318334Speter      REAL_VALUE_FROM_CONST_DOUBLE (d1, op1);
453418334Speter      equal = REAL_VALUES_EQUAL (d0, d1);
453518334Speter      op0lt = op0ltu = REAL_VALUES_LESS (d0, d1);
453618334Speter      op1lt = op1ltu = REAL_VALUES_LESS (d1, d0);
453718334Speter      set_float_handler (NULL_PTR);
453818334Speter    }
453918334Speter#endif  /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
454018334Speter
454118334Speter  /* Otherwise, see if the operands are both integers.  */
454218334Speter  else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode)
454318334Speter	   && (GET_CODE (op0) == CONST_DOUBLE || GET_CODE (op0) == CONST_INT)
454418334Speter	   && (GET_CODE (op1) == CONST_DOUBLE || GET_CODE (op1) == CONST_INT))
454518334Speter    {
454618334Speter      int width = GET_MODE_BITSIZE (mode);
454718334Speter      HOST_WIDE_INT l0s, h0s, l1s, h1s;
454818334Speter      unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u;
454918334Speter
455018334Speter      /* Get the two words comprising each integer constant.  */
455118334Speter      if (GET_CODE (op0) == CONST_DOUBLE)
455218334Speter	{
455318334Speter	  l0u = l0s = CONST_DOUBLE_LOW (op0);
455418334Speter	  h0u = h0s = CONST_DOUBLE_HIGH (op0);
455518334Speter	}
455618334Speter      else
455718334Speter	{
455818334Speter	  l0u = l0s = INTVAL (op0);
455918334Speter	  h0u = 0, h0s = l0s < 0 ? -1 : 0;
456018334Speter	}
456118334Speter
456218334Speter      if (GET_CODE (op1) == CONST_DOUBLE)
456318334Speter	{
456418334Speter	  l1u = l1s = CONST_DOUBLE_LOW (op1);
456518334Speter	  h1u = h1s = CONST_DOUBLE_HIGH (op1);
456618334Speter	}
456718334Speter      else
456818334Speter	{
456918334Speter	  l1u = l1s = INTVAL (op1);
457018334Speter	  h1u = 0, h1s = l1s < 0 ? -1 : 0;
457118334Speter	}
457218334Speter
457318334Speter      /* If WIDTH is nonzero and smaller than HOST_BITS_PER_WIDE_INT,
457418334Speter	 we have to sign or zero-extend the values.  */
457518334Speter      if (width != 0 && width <= HOST_BITS_PER_WIDE_INT)
457618334Speter	h0u = h1u = 0, h0s = l0s < 0 ? -1 : 0, h1s = l1s < 0 ? -1 : 0;
457718334Speter
457818334Speter      if (width != 0 && width < HOST_BITS_PER_WIDE_INT)
457918334Speter	{
458018334Speter	  l0u &= ((HOST_WIDE_INT) 1 << width) - 1;
458118334Speter	  l1u &= ((HOST_WIDE_INT) 1 << width) - 1;
458218334Speter
458318334Speter	  if (l0s & ((HOST_WIDE_INT) 1 << (width - 1)))
458418334Speter	    l0s |= ((HOST_WIDE_INT) (-1) << width);
458518334Speter
458618334Speter	  if (l1s & ((HOST_WIDE_INT) 1 << (width - 1)))
458718334Speter	    l1s |= ((HOST_WIDE_INT) (-1) << width);
458818334Speter	}
458918334Speter
459018334Speter      equal = (h0u == h1u && l0u == l1u);
459118334Speter      op0lt = (h0s < h1s || (h0s == h1s && l0s < l1s));
459218334Speter      op1lt = (h1s < h0s || (h1s == h0s && l1s < l0s));
459318334Speter      op0ltu = (h0u < h1u || (h0u == h1u && l0u < l1u));
459418334Speter      op1ltu = (h1u < h0u || (h1u == h0u && l1u < l0u));
459518334Speter    }
459618334Speter
459718334Speter  /* Otherwise, there are some code-specific tests we can make.  */
459818334Speter  else
459918334Speter    {
460018334Speter      switch (code)
460118334Speter	{
460218334Speter	case EQ:
460318334Speter	  /* References to the frame plus a constant or labels cannot
460418334Speter	     be zero, but a SYMBOL_REF can due to #pragma weak.  */
460518334Speter	  if (((NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
460618334Speter	       || GET_CODE (op0) == LABEL_REF)
460718334Speter#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
460818334Speter	      /* On some machines, the ap reg can be 0 sometimes.  */
460918334Speter	      && op0 != arg_pointer_rtx
461018334Speter#endif
461118334Speter		)
461218334Speter	    return const0_rtx;
461318334Speter	  break;
461418334Speter
461518334Speter	case NE:
461618334Speter	  if (((NONZERO_BASE_PLUS_P (op0) && op1 == const0_rtx)
461718334Speter	       || GET_CODE (op0) == LABEL_REF)
461818334Speter#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
461918334Speter	      && op0 != arg_pointer_rtx
462018334Speter#endif
462118334Speter	      )
462218334Speter	    return const_true_rtx;
462318334Speter	  break;
462418334Speter
462518334Speter	case GEU:
462618334Speter	  /* Unsigned values are never negative.  */
462718334Speter	  if (op1 == const0_rtx)
462818334Speter	    return const_true_rtx;
462918334Speter	  break;
463018334Speter
463118334Speter	case LTU:
463218334Speter	  if (op1 == const0_rtx)
463318334Speter	    return const0_rtx;
463418334Speter	  break;
463518334Speter
463618334Speter	case LEU:
463718334Speter	  /* Unsigned values are never greater than the largest
463818334Speter	     unsigned value.  */
463918334Speter	  if (GET_CODE (op1) == CONST_INT
464018334Speter	      && INTVAL (op1) == GET_MODE_MASK (mode)
464118334Speter	    && INTEGRAL_MODE_P (mode))
464218334Speter	  return const_true_rtx;
464318334Speter	  break;
464418334Speter
464518334Speter	case GTU:
464618334Speter	  if (GET_CODE (op1) == CONST_INT
464718334Speter	      && INTVAL (op1) == GET_MODE_MASK (mode)
464818334Speter	      && INTEGRAL_MODE_P (mode))
464918334Speter	    return const0_rtx;
465018334Speter	  break;
465118334Speter	}
465218334Speter
465318334Speter      return 0;
465418334Speter    }
465518334Speter
465618334Speter  /* If we reach here, EQUAL, OP0LT, OP0LTU, OP1LT, and OP1LTU are set
465718334Speter     as appropriate.  */
465818334Speter  switch (code)
465918334Speter    {
466018334Speter    case EQ:
466118334Speter      return equal ? const_true_rtx : const0_rtx;
466218334Speter    case NE:
466318334Speter      return ! equal ? const_true_rtx : const0_rtx;
466418334Speter    case LT:
466518334Speter      return op0lt ? const_true_rtx : const0_rtx;
466618334Speter    case GT:
466718334Speter      return op1lt ? const_true_rtx : const0_rtx;
466818334Speter    case LTU:
466918334Speter      return op0ltu ? const_true_rtx : const0_rtx;
467018334Speter    case GTU:
467118334Speter      return op1ltu ? const_true_rtx : const0_rtx;
467218334Speter    case LE:
467318334Speter      return equal || op0lt ? const_true_rtx : const0_rtx;
467418334Speter    case GE:
467518334Speter      return equal || op1lt ? const_true_rtx : const0_rtx;
467618334Speter    case LEU:
467718334Speter      return equal || op0ltu ? const_true_rtx : const0_rtx;
467818334Speter    case GEU:
467918334Speter      return equal || op1ltu ? const_true_rtx : const0_rtx;
468018334Speter    }
468118334Speter
468218334Speter  abort ();
468318334Speter}
468418334Speter
468518334Speter/* Simplify CODE, an operation with result mode MODE and three operands,
468618334Speter   OP0, OP1, and OP2.  OP0_MODE was the mode of OP0 before it became
468718334Speter   a constant.  Return 0 if no simplifications is possible.  */
468818334Speter
468918334Speterrtx
469018334Spetersimplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
469118334Speter     enum rtx_code code;
469218334Speter     enum machine_mode mode, op0_mode;
469318334Speter     rtx op0, op1, op2;
469418334Speter{
469518334Speter  int width = GET_MODE_BITSIZE (mode);
469618334Speter
469718334Speter  /* VOIDmode means "infinite" precision.  */
469818334Speter  if (width == 0)
469918334Speter    width = HOST_BITS_PER_WIDE_INT;
470018334Speter
470118334Speter  switch (code)
470218334Speter    {
470318334Speter    case SIGN_EXTRACT:
470418334Speter    case ZERO_EXTRACT:
470518334Speter      if (GET_CODE (op0) == CONST_INT
470618334Speter	  && GET_CODE (op1) == CONST_INT
470718334Speter	  && GET_CODE (op2) == CONST_INT
470818334Speter	  && INTVAL (op1) + INTVAL (op2) <= GET_MODE_BITSIZE (op0_mode)
470918334Speter	  && width <= HOST_BITS_PER_WIDE_INT)
471018334Speter	{
471118334Speter	  /* Extracting a bit-field from a constant */
471218334Speter	  HOST_WIDE_INT val = INTVAL (op0);
471318334Speter
471418334Speter	  if (BITS_BIG_ENDIAN)
471518334Speter	    val >>= (GET_MODE_BITSIZE (op0_mode)
471618334Speter		     - INTVAL (op2) - INTVAL (op1));
471718334Speter	  else
471818334Speter	    val >>= INTVAL (op2);
471918334Speter
472018334Speter	  if (HOST_BITS_PER_WIDE_INT != INTVAL (op1))
472118334Speter	    {
472218334Speter	      /* First zero-extend.  */
472318334Speter	      val &= ((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1;
472418334Speter	      /* If desired, propagate sign bit.  */
472518334Speter	      if (code == SIGN_EXTRACT
472618334Speter		  && (val & ((HOST_WIDE_INT) 1 << (INTVAL (op1) - 1))))
472718334Speter		val |= ~ (((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1);
472818334Speter	    }
472918334Speter
473018334Speter	  /* Clear the bits that don't belong in our mode,
473118334Speter	     unless they and our sign bit are all one.
473218334Speter	     So we get either a reasonable negative value or a reasonable
473318334Speter	     unsigned value for this mode.  */
473418334Speter	  if (width < HOST_BITS_PER_WIDE_INT
473518334Speter	      && ((val & ((HOST_WIDE_INT) (-1) << (width - 1)))
473618334Speter		  != ((HOST_WIDE_INT) (-1) << (width - 1))))
473718334Speter	    val &= ((HOST_WIDE_INT) 1 << width) - 1;
473818334Speter
473918334Speter	  return GEN_INT (val);
474018334Speter	}
474118334Speter      break;
474218334Speter
474318334Speter    case IF_THEN_ELSE:
474418334Speter      if (GET_CODE (op0) == CONST_INT)
474518334Speter	return op0 != const0_rtx ? op1 : op2;
474618334Speter      break;
474718334Speter
474818334Speter    default:
474918334Speter      abort ();
475018334Speter    }
475118334Speter
475218334Speter  return 0;
475318334Speter}
475418334Speter
475518334Speter/* If X is a nontrivial arithmetic operation on an argument
475618334Speter   for which a constant value can be determined, return
475718334Speter   the result of operating on that value, as a constant.
475818334Speter   Otherwise, return X, possibly with one or more operands
475918334Speter   modified by recursive calls to this function.
476018334Speter
476118334Speter   If X is a register whose contents are known, we do NOT
476218334Speter   return those contents here.  equiv_constant is called to
476318334Speter   perform that task.
476418334Speter
476518334Speter   INSN is the insn that we may be modifying.  If it is 0, make a copy
476618334Speter   of X before modifying it.  */
476718334Speter
476818334Speterstatic rtx
476918334Speterfold_rtx (x, insn)
477018334Speter     rtx x;
477118334Speter     rtx insn;
477218334Speter{
477318334Speter  register enum rtx_code code;
477418334Speter  register enum machine_mode mode;
477518334Speter  register char *fmt;
477618334Speter  register int i;
477718334Speter  rtx new = 0;
477818334Speter  int copied = 0;
477918334Speter  int must_swap = 0;
478018334Speter
478118334Speter  /* Folded equivalents of first two operands of X.  */
478218334Speter  rtx folded_arg0;
478318334Speter  rtx folded_arg1;
478418334Speter
478518334Speter  /* Constant equivalents of first three operands of X;
478618334Speter     0 when no such equivalent is known.  */
478718334Speter  rtx const_arg0;
478818334Speter  rtx const_arg1;
478918334Speter  rtx const_arg2;
479018334Speter
479118334Speter  /* The mode of the first operand of X.  We need this for sign and zero
479218334Speter     extends.  */
479318334Speter  enum machine_mode mode_arg0;
479418334Speter
479518334Speter  if (x == 0)
479618334Speter    return x;
479718334Speter
479818334Speter  mode = GET_MODE (x);
479918334Speter  code = GET_CODE (x);
480018334Speter  switch (code)
480118334Speter    {
480218334Speter    case CONST:
480318334Speter    case CONST_INT:
480418334Speter    case CONST_DOUBLE:
480518334Speter    case SYMBOL_REF:
480618334Speter    case LABEL_REF:
480718334Speter    case REG:
480818334Speter      /* No use simplifying an EXPR_LIST
480918334Speter	 since they are used only for lists of args
481018334Speter	 in a function call's REG_EQUAL note.  */
481118334Speter    case EXPR_LIST:
481218334Speter      return x;
481318334Speter
481418334Speter#ifdef HAVE_cc0
481518334Speter    case CC0:
481618334Speter      return prev_insn_cc0;
481718334Speter#endif
481818334Speter
481918334Speter    case PC:
482018334Speter      /* If the next insn is a CODE_LABEL followed by a jump table,
482118334Speter	 PC's value is a LABEL_REF pointing to that label.  That
482218334Speter	 lets us fold switch statements on the Vax.  */
482318334Speter      if (insn && GET_CODE (insn) == JUMP_INSN)
482418334Speter	{
482518334Speter	  rtx next = next_nonnote_insn (insn);
482618334Speter
482718334Speter	  if (next && GET_CODE (next) == CODE_LABEL
482818334Speter	      && NEXT_INSN (next) != 0
482918334Speter	      && GET_CODE (NEXT_INSN (next)) == JUMP_INSN
483018334Speter	      && (GET_CODE (PATTERN (NEXT_INSN (next))) == ADDR_VEC
483118334Speter		  || GET_CODE (PATTERN (NEXT_INSN (next))) == ADDR_DIFF_VEC))
483218334Speter	    return gen_rtx (LABEL_REF, Pmode, next);
483318334Speter	}
483418334Speter      break;
483518334Speter
483618334Speter    case SUBREG:
483718334Speter      /* See if we previously assigned a constant value to this SUBREG.  */
483818334Speter      if ((new = lookup_as_function (x, CONST_INT)) != 0
483918334Speter	  || (new = lookup_as_function (x, CONST_DOUBLE)) != 0)
484018334Speter	return new;
484118334Speter
484218334Speter      /* If this is a paradoxical SUBREG, we have no idea what value the
484318334Speter	 extra bits would have.  However, if the operand is equivalent
484418334Speter	 to a SUBREG whose operand is the same as our mode, and all the
484518334Speter	 modes are within a word, we can just use the inner operand
484618334Speter	 because these SUBREGs just say how to treat the register.
484718334Speter
484818334Speter	 Similarly if we find an integer constant.  */
484918334Speter
485018334Speter      if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
485118334Speter	{
485218334Speter	  enum machine_mode imode = GET_MODE (SUBREG_REG (x));
485318334Speter	  struct table_elt *elt;
485418334Speter
485518334Speter	  if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
485618334Speter	      && GET_MODE_SIZE (imode) <= UNITS_PER_WORD
485718334Speter	      && (elt = lookup (SUBREG_REG (x), HASH (SUBREG_REG (x), imode),
485818334Speter				imode)) != 0)
485918334Speter	    for (elt = elt->first_same_value;
486018334Speter		 elt; elt = elt->next_same_value)
486118334Speter	      {
486218334Speter		if (CONSTANT_P (elt->exp)
486318334Speter		    && GET_MODE (elt->exp) == VOIDmode)
486418334Speter		  return elt->exp;
486518334Speter
486618334Speter		if (GET_CODE (elt->exp) == SUBREG
486718334Speter		    && GET_MODE (SUBREG_REG (elt->exp)) == mode
486818334Speter		    && exp_equiv_p (elt->exp, elt->exp, 1, 0))
486918334Speter		  return copy_rtx (SUBREG_REG (elt->exp));
487018334Speter	    }
487118334Speter
487218334Speter	  return x;
487318334Speter	}
487418334Speter
487518334Speter      /* Fold SUBREG_REG.  If it changed, see if we can simplify the SUBREG.
487618334Speter	 We might be able to if the SUBREG is extracting a single word in an
487718334Speter	 integral mode or extracting the low part.  */
487818334Speter
487918334Speter      folded_arg0 = fold_rtx (SUBREG_REG (x), insn);
488018334Speter      const_arg0 = equiv_constant (folded_arg0);
488118334Speter      if (const_arg0)
488218334Speter	folded_arg0 = const_arg0;
488318334Speter
488418334Speter      if (folded_arg0 != SUBREG_REG (x))
488518334Speter	{
488618334Speter	  new = 0;
488718334Speter
488818334Speter	  if (GET_MODE_CLASS (mode) == MODE_INT
488918334Speter	      && GET_MODE_SIZE (mode) == UNITS_PER_WORD
489018334Speter	      && GET_MODE (SUBREG_REG (x)) != VOIDmode)
489118334Speter	    new = operand_subword (folded_arg0, SUBREG_WORD (x), 0,
489218334Speter				   GET_MODE (SUBREG_REG (x)));
489318334Speter	  if (new == 0 && subreg_lowpart_p (x))
489418334Speter	    new = gen_lowpart_if_possible (mode, folded_arg0);
489518334Speter	  if (new)
489618334Speter	    return new;
489718334Speter	}
489818334Speter
489918334Speter      /* If this is a narrowing SUBREG and our operand is a REG, see if
490018334Speter	 we can find an equivalence for REG that is an arithmetic operation
490118334Speter	 in a wider mode where both operands are paradoxical SUBREGs
490218334Speter	 from objects of our result mode.  In that case, we couldn't report
490318334Speter	 an equivalent value for that operation, since we don't know what the
490418334Speter	 extra bits will be.  But we can find an equivalence for this SUBREG
490518334Speter	 by folding that operation is the narrow mode.  This allows us to
490618334Speter	 fold arithmetic in narrow modes when the machine only supports
490718334Speter	 word-sized arithmetic.
490818334Speter
490918334Speter	 Also look for a case where we have a SUBREG whose operand is the
491018334Speter	 same as our result.  If both modes are smaller than a word, we
491118334Speter	 are simply interpreting a register in different modes and we
491218334Speter	 can use the inner value.  */
491318334Speter
491418334Speter      if (GET_CODE (folded_arg0) == REG
491518334Speter	  && GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (folded_arg0))
491618334Speter	  && subreg_lowpart_p (x))
491718334Speter	{
491818334Speter	  struct table_elt *elt;
491918334Speter
492018334Speter	  /* We can use HASH here since we know that canon_hash won't be
492118334Speter	     called.  */
492218334Speter	  elt = lookup (folded_arg0,
492318334Speter			HASH (folded_arg0, GET_MODE (folded_arg0)),
492418334Speter			GET_MODE (folded_arg0));
492518334Speter
492618334Speter	  if (elt)
492718334Speter	    elt = elt->first_same_value;
492818334Speter
492918334Speter	  for (; elt; elt = elt->next_same_value)
493018334Speter	    {
493118334Speter	      enum rtx_code eltcode = GET_CODE (elt->exp);
493218334Speter
493318334Speter	      /* Just check for unary and binary operations.  */
493418334Speter	      if (GET_RTX_CLASS (GET_CODE (elt->exp)) == '1'
493518334Speter		  && GET_CODE (elt->exp) != SIGN_EXTEND
493618334Speter		  && GET_CODE (elt->exp) != ZERO_EXTEND
493718334Speter		  && GET_CODE (XEXP (elt->exp, 0)) == SUBREG
493818334Speter		  && GET_MODE (SUBREG_REG (XEXP (elt->exp, 0))) == mode)
493918334Speter		{
494018334Speter		  rtx op0 = SUBREG_REG (XEXP (elt->exp, 0));
494118334Speter
494218334Speter		  if (GET_CODE (op0) != REG && ! CONSTANT_P (op0))
494318334Speter		    op0 = fold_rtx (op0, NULL_RTX);
494418334Speter
494518334Speter		  op0 = equiv_constant (op0);
494618334Speter		  if (op0)
494718334Speter		    new = simplify_unary_operation (GET_CODE (elt->exp), mode,
494818334Speter						    op0, mode);
494918334Speter		}
495018334Speter	      else if ((GET_RTX_CLASS (GET_CODE (elt->exp)) == '2'
495118334Speter			|| GET_RTX_CLASS (GET_CODE (elt->exp)) == 'c')
495218334Speter		       && eltcode != DIV && eltcode != MOD
495318334Speter		       && eltcode != UDIV && eltcode != UMOD
495418334Speter		       && eltcode != ASHIFTRT && eltcode != LSHIFTRT
495518334Speter		       && eltcode != ROTATE && eltcode != ROTATERT
495618334Speter		       && ((GET_CODE (XEXP (elt->exp, 0)) == SUBREG
495718334Speter			    && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 0)))
495818334Speter				== mode))
495918334Speter			   || CONSTANT_P (XEXP (elt->exp, 0)))
496018334Speter		       && ((GET_CODE (XEXP (elt->exp, 1)) == SUBREG
496118334Speter			    && (GET_MODE (SUBREG_REG (XEXP (elt->exp, 1)))
496218334Speter				== mode))
496318334Speter			   || CONSTANT_P (XEXP (elt->exp, 1))))
496418334Speter		{
496518334Speter		  rtx op0 = gen_lowpart_common (mode, XEXP (elt->exp, 0));
496618334Speter		  rtx op1 = gen_lowpart_common (mode, XEXP (elt->exp, 1));
496718334Speter
496818334Speter		  if (op0 && GET_CODE (op0) != REG && ! CONSTANT_P (op0))
496918334Speter		    op0 = fold_rtx (op0, NULL_RTX);
497018334Speter
497118334Speter		  if (op0)
497218334Speter		    op0 = equiv_constant (op0);
497318334Speter
497418334Speter		  if (op1 && GET_CODE (op1) != REG && ! CONSTANT_P (op1))
497518334Speter		    op1 = fold_rtx (op1, NULL_RTX);
497618334Speter
497718334Speter		  if (op1)
497818334Speter		    op1 = equiv_constant (op1);
497918334Speter
498018334Speter		  /* If we are looking for the low SImode part of
498118334Speter		     (ashift:DI c (const_int 32)), it doesn't work
498218334Speter		     to compute that in SImode, because a 32-bit shift
498318334Speter		     in SImode is unpredictable.  We know the value is 0.  */
498418334Speter		  if (op0 && op1
498518334Speter		      && GET_CODE (elt->exp) == ASHIFT
498618334Speter		      && GET_CODE (op1) == CONST_INT
498718334Speter		      && INTVAL (op1) >= GET_MODE_BITSIZE (mode))
498818334Speter		    {
498918334Speter		      if (INTVAL (op1) < GET_MODE_BITSIZE (GET_MODE (elt->exp)))
499018334Speter
499118334Speter			/* If the count fits in the inner mode's width,
499218334Speter			   but exceeds the outer mode's width,
499318334Speter			   the value will get truncated to 0
499418334Speter			   by the subreg.  */
499518334Speter			new = const0_rtx;
499618334Speter		      else
499718334Speter			/* If the count exceeds even the inner mode's width,
499818334Speter			   don't fold this expression.  */
499918334Speter			new = 0;
500018334Speter		    }
500118334Speter		  else if (op0 && op1)
500218334Speter		    new = simplify_binary_operation (GET_CODE (elt->exp), mode,
500318334Speter						     op0, op1);
500418334Speter		}
500518334Speter
500618334Speter	      else if (GET_CODE (elt->exp) == SUBREG
500718334Speter		       && GET_MODE (SUBREG_REG (elt->exp)) == mode
500818334Speter		       && (GET_MODE_SIZE (GET_MODE (folded_arg0))
500918334Speter			   <= UNITS_PER_WORD)
501018334Speter		       && exp_equiv_p (elt->exp, elt->exp, 1, 0))
501118334Speter		new = copy_rtx (SUBREG_REG (elt->exp));
501218334Speter
501318334Speter	      if (new)
501418334Speter		return new;
501518334Speter	    }
501618334Speter	}
501718334Speter
501818334Speter      return x;
501918334Speter
502018334Speter    case NOT:
502118334Speter    case NEG:
502218334Speter      /* If we have (NOT Y), see if Y is known to be (NOT Z).
502318334Speter	 If so, (NOT Y) simplifies to Z.  Similarly for NEG.  */
502418334Speter      new = lookup_as_function (XEXP (x, 0), code);
502518334Speter      if (new)
502618334Speter	return fold_rtx (copy_rtx (XEXP (new, 0)), insn);
502718334Speter      break;
502818334Speter
502918334Speter    case MEM:
503018334Speter      /* If we are not actually processing an insn, don't try to find the
503118334Speter	 best address.  Not only don't we care, but we could modify the
503218334Speter	 MEM in an invalid way since we have no insn to validate against.  */
503318334Speter      if (insn != 0)
503418334Speter	find_best_addr (insn, &XEXP (x, 0));
503518334Speter
503618334Speter      {
503718334Speter	/* Even if we don't fold in the insn itself,
503818334Speter	   we can safely do so here, in hopes of getting a constant.  */
503918334Speter	rtx addr = fold_rtx (XEXP (x, 0), NULL_RTX);
504018334Speter	rtx base = 0;
504118334Speter	HOST_WIDE_INT offset = 0;
504218334Speter
504318334Speter	if (GET_CODE (addr) == REG
504418334Speter	    && REGNO_QTY_VALID_P (REGNO (addr))
504518334Speter	    && GET_MODE (addr) == qty_mode[reg_qty[REGNO (addr)]]
504618334Speter	    && qty_const[reg_qty[REGNO (addr)]] != 0)
504718334Speter	  addr = qty_const[reg_qty[REGNO (addr)]];
504818334Speter
504918334Speter	/* If address is constant, split it into a base and integer offset.  */
505018334Speter	if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
505118334Speter	  base = addr;
505218334Speter	else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS
505318334Speter		 && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
505418334Speter	  {
505518334Speter	    base = XEXP (XEXP (addr, 0), 0);
505618334Speter	    offset = INTVAL (XEXP (XEXP (addr, 0), 1));
505718334Speter	  }
505818334Speter	else if (GET_CODE (addr) == LO_SUM
505918334Speter		 && GET_CODE (XEXP (addr, 1)) == SYMBOL_REF)
506018334Speter	  base = XEXP (addr, 1);
506118334Speter
506218334Speter	/* If this is a constant pool reference, we can fold it into its
506318334Speter	   constant to allow better value tracking.  */
506418334Speter	if (base && GET_CODE (base) == SYMBOL_REF
506518334Speter	    && CONSTANT_POOL_ADDRESS_P (base))
506618334Speter	  {
506718334Speter	    rtx constant = get_pool_constant (base);
506818334Speter	    enum machine_mode const_mode = get_pool_mode (base);
506918334Speter	    rtx new;
507018334Speter
507118334Speter	    if (CONSTANT_P (constant) && GET_CODE (constant) != CONST_INT)
507218334Speter	      constant_pool_entries_cost = COST (constant);
507318334Speter
507418334Speter	    /* If we are loading the full constant, we have an equivalence.  */
507518334Speter	    if (offset == 0 && mode == const_mode)
507618334Speter	      return constant;
507718334Speter
507818334Speter	    /* If this actually isn't a constant (weird!), we can't do
507918334Speter	       anything.  Otherwise, handle the two most common cases:
508018334Speter	       extracting a word from a multi-word constant, and extracting
508118334Speter	       the low-order bits.  Other cases don't seem common enough to
508218334Speter	       worry about.  */
508318334Speter	    if (! CONSTANT_P (constant))
508418334Speter	      return x;
508518334Speter
508618334Speter	    if (GET_MODE_CLASS (mode) == MODE_INT
508718334Speter		&& GET_MODE_SIZE (mode) == UNITS_PER_WORD
508818334Speter		&& offset % UNITS_PER_WORD == 0
508918334Speter		&& (new = operand_subword (constant,
509018334Speter					   offset / UNITS_PER_WORD,
509118334Speter					   0, const_mode)) != 0)
509218334Speter	      return new;
509318334Speter
509418334Speter	    if (((BYTES_BIG_ENDIAN
509518334Speter		  && offset == GET_MODE_SIZE (GET_MODE (constant)) - 1)
509618334Speter		 || (! BYTES_BIG_ENDIAN && offset == 0))
509718334Speter		&& (new = gen_lowpart_if_possible (mode, constant)) != 0)
509818334Speter	      return new;
509918334Speter	  }
510018334Speter
510118334Speter	/* If this is a reference to a label at a known position in a jump
510218334Speter	   table, we also know its value.  */
510318334Speter	if (base && GET_CODE (base) == LABEL_REF)
510418334Speter	  {
510518334Speter	    rtx label = XEXP (base, 0);
510618334Speter	    rtx table_insn = NEXT_INSN (label);
510718334Speter
510818334Speter	    if (table_insn && GET_CODE (table_insn) == JUMP_INSN
510918334Speter		&& GET_CODE (PATTERN (table_insn)) == ADDR_VEC)
511018334Speter	      {
511118334Speter		rtx table = PATTERN (table_insn);
511218334Speter
511318334Speter		if (offset >= 0
511418334Speter		    && (offset / GET_MODE_SIZE (GET_MODE (table))
511518334Speter			< XVECLEN (table, 0)))
511618334Speter		  return XVECEXP (table, 0,
511718334Speter				  offset / GET_MODE_SIZE (GET_MODE (table)));
511818334Speter	      }
511918334Speter	    if (table_insn && GET_CODE (table_insn) == JUMP_INSN
512018334Speter		&& GET_CODE (PATTERN (table_insn)) == ADDR_DIFF_VEC)
512118334Speter	      {
512218334Speter		rtx table = PATTERN (table_insn);
512318334Speter
512418334Speter		if (offset >= 0
512518334Speter		    && (offset / GET_MODE_SIZE (GET_MODE (table))
512618334Speter			< XVECLEN (table, 1)))
512718334Speter		  {
512818334Speter		    offset /= GET_MODE_SIZE (GET_MODE (table));
512918334Speter		    new = gen_rtx (MINUS, Pmode, XVECEXP (table, 1, offset),
513018334Speter				   XEXP (table, 0));
513118334Speter
513218334Speter		    if (GET_MODE (table) != Pmode)
513318334Speter		      new = gen_rtx (TRUNCATE, GET_MODE (table), new);
513418334Speter
513518334Speter		    /* Indicate this is a constant.  This isn't a
513618334Speter		       valid form of CONST, but it will only be used
513718334Speter		       to fold the next insns and then discarded, so
513818334Speter		       it should be safe.  */
513918334Speter		    return gen_rtx (CONST, GET_MODE (new), new);
514018334Speter		  }
514118334Speter	      }
514218334Speter	  }
514318334Speter
514418334Speter	return x;
514518334Speter      }
514618334Speter    }
514718334Speter
514818334Speter  const_arg0 = 0;
514918334Speter  const_arg1 = 0;
515018334Speter  const_arg2 = 0;
515118334Speter  mode_arg0 = VOIDmode;
515218334Speter
515318334Speter  /* Try folding our operands.
515418334Speter     Then see which ones have constant values known.  */
515518334Speter
515618334Speter  fmt = GET_RTX_FORMAT (code);
515718334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
515818334Speter    if (fmt[i] == 'e')
515918334Speter      {
516018334Speter	rtx arg = XEXP (x, i);
516118334Speter	rtx folded_arg = arg, const_arg = 0;
516218334Speter	enum machine_mode mode_arg = GET_MODE (arg);
516318334Speter	rtx cheap_arg, expensive_arg;
516418334Speter	rtx replacements[2];
516518334Speter	int j;
516618334Speter
516718334Speter	/* Most arguments are cheap, so handle them specially.  */
516818334Speter	switch (GET_CODE (arg))
516918334Speter	  {
517018334Speter	  case REG:
517118334Speter	    /* This is the same as calling equiv_constant; it is duplicated
517218334Speter	       here for speed.  */
517318334Speter	    if (REGNO_QTY_VALID_P (REGNO (arg))
517418334Speter		&& qty_const[reg_qty[REGNO (arg)]] != 0
517518334Speter		&& GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != REG
517618334Speter		&& GET_CODE (qty_const[reg_qty[REGNO (arg)]]) != PLUS)
517718334Speter	      const_arg
517818334Speter		= gen_lowpart_if_possible (GET_MODE (arg),
517918334Speter					   qty_const[reg_qty[REGNO (arg)]]);
518018334Speter	    break;
518118334Speter
518218334Speter	  case CONST:
518318334Speter	  case CONST_INT:
518418334Speter	  case SYMBOL_REF:
518518334Speter	  case LABEL_REF:
518618334Speter	  case CONST_DOUBLE:
518718334Speter	    const_arg = arg;
518818334Speter	    break;
518918334Speter
519018334Speter#ifdef HAVE_cc0
519118334Speter	  case CC0:
519218334Speter	    folded_arg = prev_insn_cc0;
519318334Speter	    mode_arg = prev_insn_cc0_mode;
519418334Speter	    const_arg = equiv_constant (folded_arg);
519518334Speter	    break;
519618334Speter#endif
519718334Speter
519818334Speter	  default:
519918334Speter	    folded_arg = fold_rtx (arg, insn);
520018334Speter	    const_arg = equiv_constant (folded_arg);
520118334Speter	  }
520218334Speter
520318334Speter	/* For the first three operands, see if the operand
520418334Speter	   is constant or equivalent to a constant.  */
520518334Speter	switch (i)
520618334Speter	  {
520718334Speter	  case 0:
520818334Speter	    folded_arg0 = folded_arg;
520918334Speter	    const_arg0 = const_arg;
521018334Speter	    mode_arg0 = mode_arg;
521118334Speter	    break;
521218334Speter	  case 1:
521318334Speter	    folded_arg1 = folded_arg;
521418334Speter	    const_arg1 = const_arg;
521518334Speter	    break;
521618334Speter	  case 2:
521718334Speter	    const_arg2 = const_arg;
521818334Speter	    break;
521918334Speter	  }
522018334Speter
522118334Speter	/* Pick the least expensive of the folded argument and an
522218334Speter	   equivalent constant argument.  */
522318334Speter	if (const_arg == 0 || const_arg == folded_arg
522418334Speter	    || COST (const_arg) > COST (folded_arg))
522518334Speter	  cheap_arg = folded_arg, expensive_arg = const_arg;
522618334Speter	else
522718334Speter	  cheap_arg = const_arg, expensive_arg = folded_arg;
522818334Speter
522918334Speter	/* Try to replace the operand with the cheapest of the two
523018334Speter	   possibilities.  If it doesn't work and this is either of the first
523118334Speter	   two operands of a commutative operation, try swapping them.
523218334Speter	   If THAT fails, try the more expensive, provided it is cheaper
523318334Speter	   than what is already there.  */
523418334Speter
523518334Speter	if (cheap_arg == XEXP (x, i))
523618334Speter	  continue;
523718334Speter
523818334Speter	if (insn == 0 && ! copied)
523918334Speter	  {
524018334Speter	    x = copy_rtx (x);
524118334Speter	    copied = 1;
524218334Speter	  }
524318334Speter
524418334Speter	replacements[0] = cheap_arg, replacements[1] = expensive_arg;
524518334Speter	for (j = 0;
524618334Speter	     j < 2 && replacements[j]
524718334Speter	     && COST (replacements[j]) < COST (XEXP (x, i));
524818334Speter	     j++)
524918334Speter	  {
525018334Speter	    if (validate_change (insn, &XEXP (x, i), replacements[j], 0))
525118334Speter	      break;
525218334Speter
525318334Speter	    if (code == NE || code == EQ || GET_RTX_CLASS (code) == 'c')
525418334Speter	      {
525518334Speter		validate_change (insn, &XEXP (x, i), XEXP (x, 1 - i), 1);
525618334Speter		validate_change (insn, &XEXP (x, 1 - i), replacements[j], 1);
525718334Speter
525818334Speter		if (apply_change_group ())
525918334Speter		  {
526018334Speter		    /* Swap them back to be invalid so that this loop can
526118334Speter		       continue and flag them to be swapped back later.  */
526218334Speter		    rtx tem;
526318334Speter
526418334Speter		    tem = XEXP (x, 0); XEXP (x, 0) = XEXP (x, 1);
526518334Speter				       XEXP (x, 1) = tem;
526618334Speter		    must_swap = 1;
526718334Speter		    break;
526818334Speter		  }
526918334Speter	      }
527018334Speter	  }
527118334Speter      }
527218334Speter
527318334Speter    else if (fmt[i] == 'E')
527418334Speter      /* Don't try to fold inside of a vector of expressions.
527518334Speter	 Doing nothing is harmless.  */
527618334Speter      ;
527718334Speter
527818334Speter  /* If a commutative operation, place a constant integer as the second
527918334Speter     operand unless the first operand is also a constant integer.  Otherwise,
528018334Speter     place any constant second unless the first operand is also a constant.  */
528118334Speter
528218334Speter  if (code == EQ || code == NE || GET_RTX_CLASS (code) == 'c')
528318334Speter    {
528418334Speter      if (must_swap || (const_arg0
528518334Speter	  		&& (const_arg1 == 0
528618334Speter	      		    || (GET_CODE (const_arg0) == CONST_INT
528718334Speter			        && GET_CODE (const_arg1) != CONST_INT))))
528818334Speter	{
528918334Speter	  register rtx tem = XEXP (x, 0);
529018334Speter
529118334Speter	  if (insn == 0 && ! copied)
529218334Speter	    {
529318334Speter	      x = copy_rtx (x);
529418334Speter	      copied = 1;
529518334Speter	    }
529618334Speter
529718334Speter	  validate_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
529818334Speter	  validate_change (insn, &XEXP (x, 1), tem, 1);
529918334Speter	  if (apply_change_group ())
530018334Speter	    {
530118334Speter	      tem = const_arg0, const_arg0 = const_arg1, const_arg1 = tem;
530218334Speter	      tem = folded_arg0, folded_arg0 = folded_arg1, folded_arg1 = tem;
530318334Speter	    }
530418334Speter	}
530518334Speter    }
530618334Speter
530718334Speter  /* If X is an arithmetic operation, see if we can simplify it.  */
530818334Speter
530918334Speter  switch (GET_RTX_CLASS (code))
531018334Speter    {
531118334Speter    case '1':
531218334Speter      {
531318334Speter	int is_const = 0;
531418334Speter
531518334Speter	/* We can't simplify extension ops unless we know the
531618334Speter	   original mode.  */
531718334Speter	if ((code == ZERO_EXTEND || code == SIGN_EXTEND)
531818334Speter	    && mode_arg0 == VOIDmode)
531918334Speter	  break;
532018334Speter
532118334Speter	/* If we had a CONST, strip it off and put it back later if we
532218334Speter	   fold.  */
532318334Speter	if (const_arg0 != 0 && GET_CODE (const_arg0) == CONST)
532418334Speter	  is_const = 1, const_arg0 = XEXP (const_arg0, 0);
532518334Speter
532618334Speter	new = simplify_unary_operation (code, mode,
532718334Speter					const_arg0 ? const_arg0 : folded_arg0,
532818334Speter					mode_arg0);
532918334Speter	if (new != 0 && is_const)
533018334Speter	  new = gen_rtx (CONST, mode, new);
533118334Speter      }
533218334Speter      break;
533318334Speter
533418334Speter    case '<':
533518334Speter      /* See what items are actually being compared and set FOLDED_ARG[01]
533618334Speter	 to those values and CODE to the actual comparison code.  If any are
533718334Speter	 constant, set CONST_ARG0 and CONST_ARG1 appropriately.  We needn't
533818334Speter	 do anything if both operands are already known to be constant.  */
533918334Speter
534018334Speter      if (const_arg0 == 0 || const_arg1 == 0)
534118334Speter	{
534218334Speter	  struct table_elt *p0, *p1;
534318334Speter	  rtx true = const_true_rtx, false = const0_rtx;
534418334Speter	  enum machine_mode mode_arg1;
534518334Speter
534618334Speter#ifdef FLOAT_STORE_FLAG_VALUE
534718334Speter	  if (GET_MODE_CLASS (mode) == MODE_FLOAT)
534818334Speter	    {
534918334Speter	      true = CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE,
535018334Speter						   mode);
535118334Speter	      false = CONST0_RTX (mode);
535218334Speter	    }
535318334Speter#endif
535418334Speter
535518334Speter	  code = find_comparison_args (code, &folded_arg0, &folded_arg1,
535618334Speter				       &mode_arg0, &mode_arg1);
535718334Speter	  const_arg0 = equiv_constant (folded_arg0);
535818334Speter	  const_arg1 = equiv_constant (folded_arg1);
535918334Speter
536018334Speter	  /* If the mode is VOIDmode or a MODE_CC mode, we don't know
536118334Speter	     what kinds of things are being compared, so we can't do
536218334Speter	     anything with this comparison.  */
536318334Speter
536418334Speter	  if (mode_arg0 == VOIDmode || GET_MODE_CLASS (mode_arg0) == MODE_CC)
536518334Speter	    break;
536618334Speter
536718334Speter	  /* If we do not now have two constants being compared, see if we
536818334Speter	     can nevertheless deduce some things about the comparison.  */
536918334Speter	  if (const_arg0 == 0 || const_arg1 == 0)
537018334Speter	    {
537118334Speter	      /* Is FOLDED_ARG0 frame-pointer plus a constant?  Or non-explicit
537218334Speter		 constant?  These aren't zero, but we don't know their sign. */
537318334Speter	      if (const_arg1 == const0_rtx
537418334Speter		  && (NONZERO_BASE_PLUS_P (folded_arg0)
537518334Speter#if 0  /* Sad to say, on sysvr4, #pragma weak can make a symbol address
537618334Speter	  come out as 0.  */
537718334Speter		      || GET_CODE (folded_arg0) == SYMBOL_REF
537818334Speter#endif
537918334Speter		      || GET_CODE (folded_arg0) == LABEL_REF
538018334Speter		      || GET_CODE (folded_arg0) == CONST))
538118334Speter		{
538218334Speter		  if (code == EQ)
538318334Speter		    return false;
538418334Speter		  else if (code == NE)
538518334Speter		    return true;
538618334Speter		}
538718334Speter
538818334Speter	      /* See if the two operands are the same.  We don't do this
538918334Speter		 for IEEE floating-point since we can't assume x == x
539018334Speter		 since x might be a NaN.  */
539118334Speter
539218334Speter	      if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
539318334Speter		   || ! FLOAT_MODE_P (mode_arg0) || flag_fast_math)
539418334Speter		  && (folded_arg0 == folded_arg1
539518334Speter		      || (GET_CODE (folded_arg0) == REG
539618334Speter			  && GET_CODE (folded_arg1) == REG
539718334Speter			  && (reg_qty[REGNO (folded_arg0)]
539818334Speter			      == reg_qty[REGNO (folded_arg1)]))
539918334Speter		      || ((p0 = lookup (folded_arg0,
540018334Speter					(safe_hash (folded_arg0, mode_arg0)
540118334Speter					 % NBUCKETS), mode_arg0))
540218334Speter			  && (p1 = lookup (folded_arg1,
540318334Speter					   (safe_hash (folded_arg1, mode_arg0)
540418334Speter					    % NBUCKETS), mode_arg0))
540518334Speter			  && p0->first_same_value == p1->first_same_value)))
540618334Speter		return ((code == EQ || code == LE || code == GE
540718334Speter			 || code == LEU || code == GEU)
540818334Speter			? true : false);
540918334Speter
541018334Speter	      /* If FOLDED_ARG0 is a register, see if the comparison we are
541118334Speter		 doing now is either the same as we did before or the reverse
541218334Speter		 (we only check the reverse if not floating-point).  */
541318334Speter	      else if (GET_CODE (folded_arg0) == REG)
541418334Speter		{
541518334Speter		  int qty = reg_qty[REGNO (folded_arg0)];
541618334Speter
541718334Speter		  if (REGNO_QTY_VALID_P (REGNO (folded_arg0))
541818334Speter		      && (comparison_dominates_p (qty_comparison_code[qty], code)
541918334Speter			  || (comparison_dominates_p (qty_comparison_code[qty],
542018334Speter						      reverse_condition (code))
542118334Speter			      && ! FLOAT_MODE_P (mode_arg0)))
542218334Speter		      && (rtx_equal_p (qty_comparison_const[qty], folded_arg1)
542318334Speter			  || (const_arg1
542418334Speter			      && rtx_equal_p (qty_comparison_const[qty],
542518334Speter					      const_arg1))
542618334Speter			  || (GET_CODE (folded_arg1) == REG
542718334Speter			      && (reg_qty[REGNO (folded_arg1)]
542818334Speter				  == qty_comparison_qty[qty]))))
542918334Speter		    return (comparison_dominates_p (qty_comparison_code[qty],
543018334Speter						    code)
543118334Speter			    ? true : false);
543218334Speter		}
543318334Speter	    }
543418334Speter	}
543518334Speter
543618334Speter      /* If we are comparing against zero, see if the first operand is
543718334Speter	 equivalent to an IOR with a constant.  If so, we may be able to
543818334Speter	 determine the result of this comparison.  */
543918334Speter
544018334Speter      if (const_arg1 == const0_rtx)
544118334Speter	{
544218334Speter	  rtx y = lookup_as_function (folded_arg0, IOR);
544318334Speter	  rtx inner_const;
544418334Speter
544518334Speter	  if (y != 0
544618334Speter	      && (inner_const = equiv_constant (XEXP (y, 1))) != 0
544718334Speter	      && GET_CODE (inner_const) == CONST_INT
544818334Speter	      && INTVAL (inner_const) != 0)
544918334Speter	    {
545018334Speter	      int sign_bitnum = GET_MODE_BITSIZE (mode_arg0) - 1;
545118334Speter	      int has_sign = (HOST_BITS_PER_WIDE_INT >= sign_bitnum
545218334Speter			      && (INTVAL (inner_const)
545318334Speter				  & ((HOST_WIDE_INT) 1 << sign_bitnum)));
545418334Speter	      rtx true = const_true_rtx, false = const0_rtx;
545518334Speter
545618334Speter#ifdef FLOAT_STORE_FLAG_VALUE
545718334Speter	      if (GET_MODE_CLASS (mode) == MODE_FLOAT)
545818334Speter		{
545918334Speter		  true = CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE,
546018334Speter						       mode);
546118334Speter		  false = CONST0_RTX (mode);
546218334Speter		}
546318334Speter#endif
546418334Speter
546518334Speter	      switch (code)
546618334Speter		{
546718334Speter		case EQ:
546818334Speter		  return false;
546918334Speter		case NE:
547018334Speter		  return true;
547118334Speter		case LT:  case LE:
547218334Speter		  if (has_sign)
547318334Speter		    return true;
547418334Speter		  break;
547518334Speter		case GT:  case GE:
547618334Speter		  if (has_sign)
547718334Speter		    return false;
547818334Speter		  break;
547918334Speter		}
548018334Speter	    }
548118334Speter	}
548218334Speter
548318334Speter      new = simplify_relational_operation (code, mode_arg0,
548418334Speter					   const_arg0 ? const_arg0 : folded_arg0,
548518334Speter					   const_arg1 ? const_arg1 : folded_arg1);
548618334Speter#ifdef FLOAT_STORE_FLAG_VALUE
548718334Speter      if (new != 0 && GET_MODE_CLASS (mode) == MODE_FLOAT)
548818334Speter	new = ((new == const0_rtx) ? CONST0_RTX (mode)
548918334Speter	       : CONST_DOUBLE_FROM_REAL_VALUE (FLOAT_STORE_FLAG_VALUE, mode));
549018334Speter#endif
549118334Speter      break;
549218334Speter
549318334Speter    case '2':
549418334Speter    case 'c':
549518334Speter      switch (code)
549618334Speter	{
549718334Speter	case PLUS:
549818334Speter	  /* If the second operand is a LABEL_REF, see if the first is a MINUS
549918334Speter	     with that LABEL_REF as its second operand.  If so, the result is
550018334Speter	     the first operand of that MINUS.  This handles switches with an
550118334Speter	     ADDR_DIFF_VEC table.  */
550218334Speter	  if (const_arg1 && GET_CODE (const_arg1) == LABEL_REF)
550318334Speter	    {
550418334Speter	      rtx y
550518334Speter		= GET_CODE (folded_arg0) == MINUS ? folded_arg0
550618334Speter		  : lookup_as_function (folded_arg0, MINUS);
550718334Speter
550818334Speter	      if (y != 0 && GET_CODE (XEXP (y, 1)) == LABEL_REF
550918334Speter		  && XEXP (XEXP (y, 1), 0) == XEXP (const_arg1, 0))
551018334Speter		return XEXP (y, 0);
551118334Speter
551218334Speter	      /* Now try for a CONST of a MINUS like the above.  */
551318334Speter	      if ((y = (GET_CODE (folded_arg0) == CONST ? folded_arg0
551418334Speter			: lookup_as_function (folded_arg0, CONST))) != 0
551518334Speter		  && GET_CODE (XEXP (y, 0)) == MINUS
551618334Speter		  && GET_CODE (XEXP (XEXP (y, 0), 1)) == LABEL_REF
551718334Speter		  && XEXP (XEXP (XEXP (y, 0),1), 0) == XEXP (const_arg1, 0))
551818334Speter		return XEXP (XEXP (y, 0), 0);
551918334Speter	    }
552018334Speter
552118334Speter	  /* Likewise if the operands are in the other order.  */
552218334Speter	  if (const_arg0 && GET_CODE (const_arg0) == LABEL_REF)
552318334Speter	    {
552418334Speter	      rtx y
552518334Speter		= GET_CODE (folded_arg1) == MINUS ? folded_arg1
552618334Speter		  : lookup_as_function (folded_arg1, MINUS);
552718334Speter
552818334Speter	      if (y != 0 && GET_CODE (XEXP (y, 1)) == LABEL_REF
552918334Speter		  && XEXP (XEXP (y, 1), 0) == XEXP (const_arg0, 0))
553018334Speter		return XEXP (y, 0);
553118334Speter
553218334Speter	      /* Now try for a CONST of a MINUS like the above.  */
553318334Speter	      if ((y = (GET_CODE (folded_arg1) == CONST ? folded_arg1
553418334Speter			: lookup_as_function (folded_arg1, CONST))) != 0
553518334Speter		  && GET_CODE (XEXP (y, 0)) == MINUS
553618334Speter		  && GET_CODE (XEXP (XEXP (y, 0), 1)) == LABEL_REF
553718334Speter		  && XEXP (XEXP (XEXP (y, 0),1), 0) == XEXP (const_arg0, 0))
553818334Speter		return XEXP (XEXP (y, 0), 0);
553918334Speter	    }
554018334Speter
554118334Speter	  /* If second operand is a register equivalent to a negative
554218334Speter	     CONST_INT, see if we can find a register equivalent to the
554318334Speter	     positive constant.  Make a MINUS if so.  Don't do this for
554418334Speter	     a negative constant since we might then alternate between
554518334Speter	     chosing positive and negative constants.  Having the positive
554618334Speter	     constant previously-used is the more common case.  */
554718334Speter	  if (const_arg1 && GET_CODE (const_arg1) == CONST_INT
554818334Speter	      && INTVAL (const_arg1) < 0 && GET_CODE (folded_arg1) == REG)
554918334Speter	    {
555018334Speter	      rtx new_const = GEN_INT (- INTVAL (const_arg1));
555118334Speter	      struct table_elt *p
555218334Speter		= lookup (new_const, safe_hash (new_const, mode) % NBUCKETS,
555318334Speter			  mode);
555418334Speter
555518334Speter	      if (p)
555618334Speter		for (p = p->first_same_value; p; p = p->next_same_value)
555718334Speter		  if (GET_CODE (p->exp) == REG)
555818334Speter		    return cse_gen_binary (MINUS, mode, folded_arg0,
555918334Speter					   canon_reg (p->exp, NULL_RTX));
556018334Speter	    }
556118334Speter	  goto from_plus;
556218334Speter
556318334Speter	case MINUS:
556418334Speter	  /* If we have (MINUS Y C), see if Y is known to be (PLUS Z C2).
556518334Speter	     If so, produce (PLUS Z C2-C).  */
556618334Speter	  if (const_arg1 != 0 && GET_CODE (const_arg1) == CONST_INT)
556718334Speter	    {
556818334Speter	      rtx y = lookup_as_function (XEXP (x, 0), PLUS);
556918334Speter	      if (y && GET_CODE (XEXP (y, 1)) == CONST_INT)
557018334Speter		return fold_rtx (plus_constant (copy_rtx (y),
557118334Speter						-INTVAL (const_arg1)),
557218334Speter				 NULL_RTX);
557318334Speter	    }
557418334Speter
557518334Speter	  /* ... fall through ... */
557618334Speter
557718334Speter	from_plus:
557818334Speter	case SMIN:    case SMAX:      case UMIN:    case UMAX:
557918334Speter	case IOR:     case AND:       case XOR:
558018334Speter	case MULT:    case DIV:       case UDIV:
558118334Speter	case ASHIFT:  case LSHIFTRT:  case ASHIFTRT:
558218334Speter	  /* If we have (<op> <reg> <const_int>) for an associative OP and REG
558318334Speter	     is known to be of similar form, we may be able to replace the
558418334Speter	     operation with a combined operation.  This may eliminate the
558518334Speter	     intermediate operation if every use is simplified in this way.
558618334Speter	     Note that the similar optimization done by combine.c only works
558718334Speter	     if the intermediate operation's result has only one reference.  */
558818334Speter
558918334Speter	  if (GET_CODE (folded_arg0) == REG
559018334Speter	      && const_arg1 && GET_CODE (const_arg1) == CONST_INT)
559118334Speter	    {
559218334Speter	      int is_shift
559318334Speter		= (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT);
559418334Speter	      rtx y = lookup_as_function (folded_arg0, code);
559518334Speter	      rtx inner_const;
559618334Speter	      enum rtx_code associate_code;
559718334Speter	      rtx new_const;
559818334Speter
559918334Speter	      if (y == 0
560018334Speter		  || 0 == (inner_const
560118334Speter			   = equiv_constant (fold_rtx (XEXP (y, 1), 0)))
560218334Speter		  || GET_CODE (inner_const) != CONST_INT
560318334Speter		  /* If we have compiled a statement like
560418334Speter		     "if (x == (x & mask1))", and now are looking at
560518334Speter		     "x & mask2", we will have a case where the first operand
560618334Speter		     of Y is the same as our first operand.  Unless we detect
560718334Speter		     this case, an infinite loop will result.  */
560818334Speter		  || XEXP (y, 0) == folded_arg0)
560918334Speter		break;
561018334Speter
561118334Speter	      /* Don't associate these operations if they are a PLUS with the
561218334Speter		 same constant and it is a power of two.  These might be doable
561318334Speter		 with a pre- or post-increment.  Similarly for two subtracts of
561418334Speter		 identical powers of two with post decrement.  */
561518334Speter
561618334Speter	      if (code == PLUS && INTVAL (const_arg1) == INTVAL (inner_const)
561718334Speter		  && (0
561818334Speter#if defined(HAVE_PRE_INCREMENT) || defined(HAVE_POST_INCREMENT)
561918334Speter		      || exact_log2 (INTVAL (const_arg1)) >= 0
562018334Speter#endif
562118334Speter#if defined(HAVE_PRE_DECREMENT) || defined(HAVE_POST_DECREMENT)
562218334Speter		      || exact_log2 (- INTVAL (const_arg1)) >= 0
562318334Speter#endif
562418334Speter		  ))
562518334Speter		break;
562618334Speter
562718334Speter	      /* Compute the code used to compose the constants.  For example,
562818334Speter		 A/C1/C2 is A/(C1 * C2), so if CODE == DIV, we want MULT.  */
562918334Speter
563018334Speter	      associate_code
563118334Speter		= (code == MULT || code == DIV || code == UDIV ? MULT
563218334Speter		   : is_shift || code == PLUS || code == MINUS ? PLUS : code);
563318334Speter
563418334Speter	      new_const = simplify_binary_operation (associate_code, mode,
563518334Speter						     const_arg1, inner_const);
563618334Speter
563718334Speter	      if (new_const == 0)
563818334Speter		break;
563918334Speter
564018334Speter	      /* If we are associating shift operations, don't let this
564118334Speter		 produce a shift of the size of the object or larger.
564218334Speter		 This could occur when we follow a sign-extend by a right
564318334Speter		 shift on a machine that does a sign-extend as a pair
564418334Speter		 of shifts.  */
564518334Speter
564618334Speter	      if (is_shift && GET_CODE (new_const) == CONST_INT
564718334Speter		  && INTVAL (new_const) >= GET_MODE_BITSIZE (mode))
564818334Speter		{
564918334Speter		  /* As an exception, we can turn an ASHIFTRT of this
565018334Speter		     form into a shift of the number of bits - 1.  */
565118334Speter		  if (code == ASHIFTRT)
565218334Speter		    new_const = GEN_INT (GET_MODE_BITSIZE (mode) - 1);
565318334Speter		  else
565418334Speter		    break;
565518334Speter		}
565618334Speter
565718334Speter	      y = copy_rtx (XEXP (y, 0));
565818334Speter
565918334Speter	      /* If Y contains our first operand (the most common way this
566018334Speter		 can happen is if Y is a MEM), we would do into an infinite
566118334Speter		 loop if we tried to fold it.  So don't in that case.  */
566218334Speter
566318334Speter	      if (! reg_mentioned_p (folded_arg0, y))
566418334Speter		y = fold_rtx (y, insn);
566518334Speter
566618334Speter	      return cse_gen_binary (code, mode, y, new_const);
566718334Speter	    }
566818334Speter	}
566918334Speter
567018334Speter      new = simplify_binary_operation (code, mode,
567118334Speter				       const_arg0 ? const_arg0 : folded_arg0,
567218334Speter				       const_arg1 ? const_arg1 : folded_arg1);
567318334Speter      break;
567418334Speter
567518334Speter    case 'o':
567618334Speter      /* (lo_sum (high X) X) is simply X.  */
567718334Speter      if (code == LO_SUM && const_arg0 != 0
567818334Speter	  && GET_CODE (const_arg0) == HIGH
567918334Speter	  && rtx_equal_p (XEXP (const_arg0, 0), const_arg1))
568018334Speter	return const_arg1;
568118334Speter      break;
568218334Speter
568318334Speter    case '3':
568418334Speter    case 'b':
568518334Speter      new = simplify_ternary_operation (code, mode, mode_arg0,
568618334Speter					const_arg0 ? const_arg0 : folded_arg0,
568718334Speter					const_arg1 ? const_arg1 : folded_arg1,
568818334Speter					const_arg2 ? const_arg2 : XEXP (x, 2));
568918334Speter      break;
569018334Speter    }
569118334Speter
569218334Speter  return new ? new : x;
569318334Speter}
569418334Speter
569518334Speter/* Return a constant value currently equivalent to X.
569618334Speter   Return 0 if we don't know one.  */
569718334Speter
569818334Speterstatic rtx
569918334Speterequiv_constant (x)
570018334Speter     rtx x;
570118334Speter{
570218334Speter  if (GET_CODE (x) == REG
570318334Speter      && REGNO_QTY_VALID_P (REGNO (x))
570418334Speter      && qty_const[reg_qty[REGNO (x)]])
570518334Speter    x = gen_lowpart_if_possible (GET_MODE (x), qty_const[reg_qty[REGNO (x)]]);
570618334Speter
570718334Speter  if (x != 0 && CONSTANT_P (x))
570818334Speter    return x;
570918334Speter
571018334Speter  /* If X is a MEM, try to fold it outside the context of any insn to see if
571118334Speter     it might be equivalent to a constant.  That handles the case where it
571218334Speter     is a constant-pool reference.  Then try to look it up in the hash table
571318334Speter     in case it is something whose value we have seen before.  */
571418334Speter
571518334Speter  if (GET_CODE (x) == MEM)
571618334Speter    {
571718334Speter      struct table_elt *elt;
571818334Speter
571918334Speter      x = fold_rtx (x, NULL_RTX);
572018334Speter      if (CONSTANT_P (x))
572118334Speter	return x;
572218334Speter
572318334Speter      elt = lookup (x, safe_hash (x, GET_MODE (x)) % NBUCKETS, GET_MODE (x));
572418334Speter      if (elt == 0)
572518334Speter	return 0;
572618334Speter
572718334Speter      for (elt = elt->first_same_value; elt; elt = elt->next_same_value)
572818334Speter	if (elt->is_const && CONSTANT_P (elt->exp))
572918334Speter	  return elt->exp;
573018334Speter    }
573118334Speter
573218334Speter  return 0;
573318334Speter}
573418334Speter
573518334Speter/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point
573618334Speter   number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
573718334Speter   least-significant part of X.
573818334Speter   MODE specifies how big a part of X to return.
573918334Speter
574018334Speter   If the requested operation cannot be done, 0 is returned.
574118334Speter
574218334Speter   This is similar to gen_lowpart in emit-rtl.c.  */
574318334Speter
574418334Speterrtx
574518334Spetergen_lowpart_if_possible (mode, x)
574618334Speter     enum machine_mode mode;
574718334Speter     register rtx x;
574818334Speter{
574918334Speter  rtx result = gen_lowpart_common (mode, x);
575018334Speter
575118334Speter  if (result)
575218334Speter    return result;
575318334Speter  else if (GET_CODE (x) == MEM)
575418334Speter    {
575518334Speter      /* This is the only other case we handle.  */
575618334Speter      register int offset = 0;
575718334Speter      rtx new;
575818334Speter
575918334Speter      if (WORDS_BIG_ENDIAN)
576018334Speter	offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
576118334Speter		  - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
576218334Speter      if (BYTES_BIG_ENDIAN)
576318334Speter	/* Adjust the address so that the address-after-the-data is
576418334Speter	   unchanged.  */
576518334Speter	offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
576618334Speter		   - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
576718334Speter      new = gen_rtx (MEM, mode, plus_constant (XEXP (x, 0), offset));
576818334Speter      if (! memory_address_p (mode, XEXP (new, 0)))
576918334Speter	return 0;
577018334Speter      MEM_VOLATILE_P (new) = MEM_VOLATILE_P (x);
577118334Speter      RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (x);
577218334Speter      MEM_IN_STRUCT_P (new) = MEM_IN_STRUCT_P (x);
577318334Speter      return new;
577418334Speter    }
577518334Speter  else
577618334Speter    return 0;
577718334Speter}
577818334Speter
577918334Speter/* Given INSN, a jump insn, TAKEN indicates if we are following the "taken"
578018334Speter   branch.  It will be zero if not.
578118334Speter
578218334Speter   In certain cases, this can cause us to add an equivalence.  For example,
578318334Speter   if we are following the taken case of
578418334Speter   	if (i == 2)
578518334Speter   we can add the fact that `i' and '2' are now equivalent.
578618334Speter
578718334Speter   In any case, we can record that this comparison was passed.  If the same
578818334Speter   comparison is seen later, we will know its value.  */
578918334Speter
579018334Speterstatic void
579118334Speterrecord_jump_equiv (insn, taken)
579218334Speter     rtx insn;
579318334Speter     int taken;
579418334Speter{
579518334Speter  int cond_known_true;
579618334Speter  rtx op0, op1;
579718334Speter  enum machine_mode mode, mode0, mode1;
579818334Speter  int reversed_nonequality = 0;
579918334Speter  enum rtx_code code;
580018334Speter
580118334Speter  /* Ensure this is the right kind of insn.  */
580218334Speter  if (! condjump_p (insn) || simplejump_p (insn))
580318334Speter    return;
580418334Speter
580518334Speter  /* See if this jump condition is known true or false.  */
580618334Speter  if (taken)
580718334Speter    cond_known_true = (XEXP (SET_SRC (PATTERN (insn)), 2) == pc_rtx);
580818334Speter  else
580918334Speter    cond_known_true = (XEXP (SET_SRC (PATTERN (insn)), 1) == pc_rtx);
581018334Speter
581118334Speter  /* Get the type of comparison being done and the operands being compared.
581218334Speter     If we had to reverse a non-equality condition, record that fact so we
581318334Speter     know that it isn't valid for floating-point.  */
581418334Speter  code = GET_CODE (XEXP (SET_SRC (PATTERN (insn)), 0));
581518334Speter  op0 = fold_rtx (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 0), insn);
581618334Speter  op1 = fold_rtx (XEXP (XEXP (SET_SRC (PATTERN (insn)), 0), 1), insn);
581718334Speter
581818334Speter  code = find_comparison_args (code, &op0, &op1, &mode0, &mode1);
581918334Speter  if (! cond_known_true)
582018334Speter    {
582118334Speter      reversed_nonequality = (code != EQ && code != NE);
582218334Speter      code = reverse_condition (code);
582318334Speter    }
582418334Speter
582518334Speter  /* The mode is the mode of the non-constant.  */
582618334Speter  mode = mode0;
582718334Speter  if (mode1 != VOIDmode)
582818334Speter    mode = mode1;
582918334Speter
583018334Speter  record_jump_cond (code, mode, op0, op1, reversed_nonequality);
583118334Speter}
583218334Speter
583318334Speter/* We know that comparison CODE applied to OP0 and OP1 in MODE is true.
583418334Speter   REVERSED_NONEQUALITY is nonzero if CODE had to be swapped.
583518334Speter   Make any useful entries we can with that information.  Called from
583618334Speter   above function and called recursively.  */
583718334Speter
583818334Speterstatic void
583918334Speterrecord_jump_cond (code, mode, op0, op1, reversed_nonequality)
584018334Speter     enum rtx_code code;
584118334Speter     enum machine_mode mode;
584218334Speter     rtx op0, op1;
584318334Speter     int reversed_nonequality;
584418334Speter{
584518334Speter  unsigned op0_hash, op1_hash;
584618334Speter  int op0_in_memory, op0_in_struct, op1_in_memory, op1_in_struct;
584718334Speter  struct table_elt *op0_elt, *op1_elt;
584818334Speter
584918334Speter  /* If OP0 and OP1 are known equal, and either is a paradoxical SUBREG,
585018334Speter     we know that they are also equal in the smaller mode (this is also
585118334Speter     true for all smaller modes whether or not there is a SUBREG, but
585218334Speter     is not worth testing for with no SUBREG.  */
585318334Speter
585418334Speter  /* Note that GET_MODE (op0) may not equal MODE.  */
585518334Speter  if (code == EQ && GET_CODE (op0) == SUBREG
585618334Speter      && (GET_MODE_SIZE (GET_MODE (op0))
585718334Speter	  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
585818334Speter    {
585918334Speter      enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
586018334Speter      rtx tem = gen_lowpart_if_possible (inner_mode, op1);
586118334Speter
586218334Speter      record_jump_cond (code, mode, SUBREG_REG (op0),
586318334Speter			tem ? tem : gen_rtx (SUBREG, inner_mode, op1, 0),
586418334Speter			reversed_nonequality);
586518334Speter    }
586618334Speter
586718334Speter  if (code == EQ && GET_CODE (op1) == SUBREG
586818334Speter      && (GET_MODE_SIZE (GET_MODE (op1))
586918334Speter	  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
587018334Speter    {
587118334Speter      enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
587218334Speter      rtx tem = gen_lowpart_if_possible (inner_mode, op0);
587318334Speter
587418334Speter      record_jump_cond (code, mode, SUBREG_REG (op1),
587518334Speter			tem ? tem : gen_rtx (SUBREG, inner_mode, op0, 0),
587618334Speter			reversed_nonequality);
587718334Speter    }
587818334Speter
587918334Speter  /* Similarly, if this is an NE comparison, and either is a SUBREG
588018334Speter     making a smaller mode, we know the whole thing is also NE.  */
588118334Speter
588218334Speter  /* Note that GET_MODE (op0) may not equal MODE;
588318334Speter     if we test MODE instead, we can get an infinite recursion
588418334Speter     alternating between two modes each wider than MODE.  */
588518334Speter
588618334Speter  if (code == NE && GET_CODE (op0) == SUBREG
588718334Speter      && subreg_lowpart_p (op0)
588818334Speter      && (GET_MODE_SIZE (GET_MODE (op0))
588918334Speter	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)))))
589018334Speter    {
589118334Speter      enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
589218334Speter      rtx tem = gen_lowpart_if_possible (inner_mode, op1);
589318334Speter
589418334Speter      record_jump_cond (code, mode, SUBREG_REG (op0),
589518334Speter			tem ? tem : gen_rtx (SUBREG, inner_mode, op1, 0),
589618334Speter			reversed_nonequality);
589718334Speter    }
589818334Speter
589918334Speter  if (code == NE && GET_CODE (op1) == SUBREG
590018334Speter      && subreg_lowpart_p (op1)
590118334Speter      && (GET_MODE_SIZE (GET_MODE (op1))
590218334Speter	  < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op1)))))
590318334Speter    {
590418334Speter      enum machine_mode inner_mode = GET_MODE (SUBREG_REG (op1));
590518334Speter      rtx tem = gen_lowpart_if_possible (inner_mode, op0);
590618334Speter
590718334Speter      record_jump_cond (code, mode, SUBREG_REG (op1),
590818334Speter			tem ? tem : gen_rtx (SUBREG, inner_mode, op0, 0),
590918334Speter			reversed_nonequality);
591018334Speter    }
591118334Speter
591218334Speter  /* Hash both operands.  */
591318334Speter
591418334Speter  do_not_record = 0;
591518334Speter  hash_arg_in_memory = 0;
591618334Speter  hash_arg_in_struct = 0;
591718334Speter  op0_hash = HASH (op0, mode);
591818334Speter  op0_in_memory = hash_arg_in_memory;
591918334Speter  op0_in_struct = hash_arg_in_struct;
592018334Speter
592118334Speter  if (do_not_record)
592218334Speter    return;
592318334Speter
592418334Speter  do_not_record = 0;
592518334Speter  hash_arg_in_memory = 0;
592618334Speter  hash_arg_in_struct = 0;
592718334Speter  op1_hash = HASH (op1, mode);
592818334Speter  op1_in_memory = hash_arg_in_memory;
592918334Speter  op1_in_struct = hash_arg_in_struct;
593018334Speter
593118334Speter  if (do_not_record)
593218334Speter    return;
593318334Speter
593418334Speter  /* Look up both operands.  */
593518334Speter  op0_elt = lookup (op0, op0_hash, mode);
593618334Speter  op1_elt = lookup (op1, op1_hash, mode);
593718334Speter
593818334Speter  /* If both operands are already equivalent or if they are not in the
593918334Speter     table but are identical, do nothing.  */
594018334Speter  if ((op0_elt != 0 && op1_elt != 0
594118334Speter       && op0_elt->first_same_value == op1_elt->first_same_value)
594218334Speter      || op0 == op1 || rtx_equal_p (op0, op1))
594318334Speter    return;
594418334Speter
594518334Speter  /* If we aren't setting two things equal all we can do is save this
594618334Speter     comparison.   Similarly if this is floating-point.  In the latter
594718334Speter     case, OP1 might be zero and both -0.0 and 0.0 are equal to it.
594818334Speter     If we record the equality, we might inadvertently delete code
594918334Speter     whose intent was to change -0 to +0.  */
595018334Speter
595118334Speter  if (code != EQ || FLOAT_MODE_P (GET_MODE (op0)))
595218334Speter    {
595318334Speter      /* If we reversed a floating-point comparison, if OP0 is not a
595418334Speter	 register, or if OP1 is neither a register or constant, we can't
595518334Speter	 do anything.  */
595618334Speter
595718334Speter      if (GET_CODE (op1) != REG)
595818334Speter	op1 = equiv_constant (op1);
595918334Speter
596018334Speter      if ((reversed_nonequality && FLOAT_MODE_P (mode))
596118334Speter	  || GET_CODE (op0) != REG || op1 == 0)
596218334Speter	return;
596318334Speter
596418334Speter      /* Put OP0 in the hash table if it isn't already.  This gives it a
596518334Speter	 new quantity number.  */
596618334Speter      if (op0_elt == 0)
596718334Speter	{
596818334Speter	  if (insert_regs (op0, NULL_PTR, 0))
596918334Speter	    {
597018334Speter	      rehash_using_reg (op0);
597118334Speter	      op0_hash = HASH (op0, mode);
597218334Speter
597318334Speter	      /* If OP0 is contained in OP1, this changes its hash code
597418334Speter		 as well.  Faster to rehash than to check, except
597518334Speter		 for the simple case of a constant.  */
597618334Speter	      if (! CONSTANT_P (op1))
597718334Speter		op1_hash = HASH (op1,mode);
597818334Speter	    }
597918334Speter
598018334Speter	  op0_elt = insert (op0, NULL_PTR, op0_hash, mode);
598118334Speter	  op0_elt->in_memory = op0_in_memory;
598218334Speter	  op0_elt->in_struct = op0_in_struct;
598318334Speter	}
598418334Speter
598518334Speter      qty_comparison_code[reg_qty[REGNO (op0)]] = code;
598618334Speter      if (GET_CODE (op1) == REG)
598718334Speter	{
598818334Speter	  /* Look it up again--in case op0 and op1 are the same.  */
598918334Speter	  op1_elt = lookup (op1, op1_hash, mode);
599018334Speter
599118334Speter	  /* Put OP1 in the hash table so it gets a new quantity number.  */
599218334Speter	  if (op1_elt == 0)
599318334Speter	    {
599418334Speter	      if (insert_regs (op1, NULL_PTR, 0))
599518334Speter		{
599618334Speter		  rehash_using_reg (op1);
599718334Speter		  op1_hash = HASH (op1, mode);
599818334Speter		}
599918334Speter
600018334Speter	      op1_elt = insert (op1, NULL_PTR, op1_hash, mode);
600118334Speter	      op1_elt->in_memory = op1_in_memory;
600218334Speter	      op1_elt->in_struct = op1_in_struct;
600318334Speter	    }
600418334Speter
600518334Speter	  qty_comparison_qty[reg_qty[REGNO (op0)]] = reg_qty[REGNO (op1)];
600618334Speter	  qty_comparison_const[reg_qty[REGNO (op0)]] = 0;
600718334Speter	}
600818334Speter      else
600918334Speter	{
601018334Speter	  qty_comparison_qty[reg_qty[REGNO (op0)]] = -1;
601118334Speter	  qty_comparison_const[reg_qty[REGNO (op0)]] = op1;
601218334Speter	}
601318334Speter
601418334Speter      return;
601518334Speter    }
601618334Speter
601718334Speter  /* If either side is still missing an equivalence, make it now,
601818334Speter     then merge the equivalences.  */
601918334Speter
602018334Speter  if (op0_elt == 0)
602118334Speter    {
602218334Speter      if (insert_regs (op0, NULL_PTR, 0))
602318334Speter	{
602418334Speter	  rehash_using_reg (op0);
602518334Speter	  op0_hash = HASH (op0, mode);
602618334Speter	}
602718334Speter
602818334Speter      op0_elt = insert (op0, NULL_PTR, op0_hash, mode);
602918334Speter      op0_elt->in_memory = op0_in_memory;
603018334Speter      op0_elt->in_struct = op0_in_struct;
603118334Speter    }
603218334Speter
603318334Speter  if (op1_elt == 0)
603418334Speter    {
603518334Speter      if (insert_regs (op1, NULL_PTR, 0))
603618334Speter	{
603718334Speter	  rehash_using_reg (op1);
603818334Speter	  op1_hash = HASH (op1, mode);
603918334Speter	}
604018334Speter
604118334Speter      op1_elt = insert (op1, NULL_PTR, op1_hash, mode);
604218334Speter      op1_elt->in_memory = op1_in_memory;
604318334Speter      op1_elt->in_struct = op1_in_struct;
604418334Speter    }
604518334Speter
604618334Speter  merge_equiv_classes (op0_elt, op1_elt);
604718334Speter  last_jump_equiv_class = op0_elt;
604818334Speter}
604918334Speter
605018334Speter/* CSE processing for one instruction.
605118334Speter   First simplify sources and addresses of all assignments
605218334Speter   in the instruction, using previously-computed equivalents values.
605318334Speter   Then install the new sources and destinations in the table
605418334Speter   of available values.
605518334Speter
605618334Speter   If IN_LIBCALL_BLOCK is nonzero, don't record any equivalence made in
605718334Speter   the insn.  */
605818334Speter
605918334Speter/* Data on one SET contained in the instruction.  */
606018334Speter
606118334Speterstruct set
606218334Speter{
606318334Speter  /* The SET rtx itself.  */
606418334Speter  rtx rtl;
606518334Speter  /* The SET_SRC of the rtx (the original value, if it is changing).  */
606618334Speter  rtx src;
606718334Speter  /* The hash-table element for the SET_SRC of the SET.  */
606818334Speter  struct table_elt *src_elt;
606918334Speter  /* Hash value for the SET_SRC.  */
607018334Speter  unsigned src_hash;
607118334Speter  /* Hash value for the SET_DEST.  */
607218334Speter  unsigned dest_hash;
607318334Speter  /* The SET_DEST, with SUBREG, etc., stripped.  */
607418334Speter  rtx inner_dest;
607518334Speter  /* Place where the pointer to the INNER_DEST was found.  */
607618334Speter  rtx *inner_dest_loc;
607718334Speter  /* Nonzero if the SET_SRC is in memory.  */
607818334Speter  char src_in_memory;
607918334Speter  /* Nonzero if the SET_SRC is in a structure.  */
608018334Speter  char src_in_struct;
608118334Speter  /* Nonzero if the SET_SRC contains something
608218334Speter     whose value cannot be predicted and understood.  */
608318334Speter  char src_volatile;
608418334Speter  /* Original machine mode, in case it becomes a CONST_INT.  */
608518334Speter  enum machine_mode mode;
608618334Speter  /* A constant equivalent for SET_SRC, if any.  */
608718334Speter  rtx src_const;
608818334Speter  /* Hash value of constant equivalent for SET_SRC.  */
608918334Speter  unsigned src_const_hash;
609018334Speter  /* Table entry for constant equivalent for SET_SRC, if any.  */
609118334Speter  struct table_elt *src_const_elt;
609218334Speter};
609318334Speter
609418334Speterstatic void
609518334Spetercse_insn (insn, in_libcall_block)
609618334Speter     rtx insn;
609718334Speter     int in_libcall_block;
609818334Speter{
609918334Speter  register rtx x = PATTERN (insn);
610018334Speter  register int i;
610118334Speter  rtx tem;
610218334Speter  register int n_sets = 0;
610318334Speter
610418334Speter  /* Records what this insn does to set CC0.  */
610518334Speter  rtx this_insn_cc0 = 0;
610618334Speter  enum machine_mode this_insn_cc0_mode;
610718334Speter  struct write_data writes_memory;
610818334Speter  static struct write_data init = {0, 0, 0, 0};
610918334Speter
611018334Speter  rtx src_eqv = 0;
611118334Speter  struct table_elt *src_eqv_elt = 0;
611218334Speter  int src_eqv_volatile;
611318334Speter  int src_eqv_in_memory;
611418334Speter  int src_eqv_in_struct;
611518334Speter  unsigned src_eqv_hash;
611618334Speter
611718334Speter  struct set *sets;
611818334Speter
611918334Speter  this_insn = insn;
612018334Speter  writes_memory = init;
612118334Speter
612218334Speter  /* Find all the SETs and CLOBBERs in this instruction.
612318334Speter     Record all the SETs in the array `set' and count them.
612418334Speter     Also determine whether there is a CLOBBER that invalidates
612518334Speter     all memory references, or all references at varying addresses.  */
612618334Speter
612718334Speter  if (GET_CODE (insn) == CALL_INSN)
612818334Speter    {
612918334Speter      for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
613018334Speter	if (GET_CODE (XEXP (tem, 0)) == CLOBBER)
613118334Speter          invalidate (SET_DEST (XEXP (tem, 0)), VOIDmode);
613218334Speter    }
613318334Speter
613418334Speter  if (GET_CODE (x) == SET)
613518334Speter    {
613618334Speter      sets = (struct set *) alloca (sizeof (struct set));
613718334Speter      sets[0].rtl = x;
613818334Speter
613918334Speter      /* Ignore SETs that are unconditional jumps.
614018334Speter	 They never need cse processing, so this does not hurt.
614118334Speter	 The reason is not efficiency but rather
614218334Speter	 so that we can test at the end for instructions
614318334Speter	 that have been simplified to unconditional jumps
614418334Speter	 and not be misled by unchanged instructions
614518334Speter	 that were unconditional jumps to begin with.  */
614618334Speter      if (SET_DEST (x) == pc_rtx
614718334Speter	  && GET_CODE (SET_SRC (x)) == LABEL_REF)
614818334Speter	;
614918334Speter
615018334Speter      /* Don't count call-insns, (set (reg 0) (call ...)), as a set.
615118334Speter	 The hard function value register is used only once, to copy to
615218334Speter	 someplace else, so it isn't worth cse'ing (and on 80386 is unsafe)!
615318334Speter	 Ensure we invalidate the destination register.  On the 80386 no
615418334Speter	 other code would invalidate it since it is a fixed_reg.
615518334Speter	 We need not check the return of apply_change_group; see canon_reg. */
615618334Speter
615718334Speter      else if (GET_CODE (SET_SRC (x)) == CALL)
615818334Speter	{
615918334Speter	  canon_reg (SET_SRC (x), insn);
616018334Speter	  apply_change_group ();
616118334Speter	  fold_rtx (SET_SRC (x), insn);
616218334Speter	  invalidate (SET_DEST (x), VOIDmode);
616318334Speter	}
616418334Speter      else
616518334Speter	n_sets = 1;
616618334Speter    }
616718334Speter  else if (GET_CODE (x) == PARALLEL)
616818334Speter    {
616918334Speter      register int lim = XVECLEN (x, 0);
617018334Speter
617118334Speter      sets = (struct set *) alloca (lim * sizeof (struct set));
617218334Speter
617318334Speter      /* Find all regs explicitly clobbered in this insn,
617418334Speter	 and ensure they are not replaced with any other regs
617518334Speter	 elsewhere in this insn.
617618334Speter	 When a reg that is clobbered is also used for input,
617718334Speter	 we should presume that that is for a reason,
617818334Speter	 and we should not substitute some other register
617918334Speter	 which is not supposed to be clobbered.
618018334Speter	 Therefore, this loop cannot be merged into the one below
618118334Speter	 because a CALL may precede a CLOBBER and refer to the
618218334Speter	 value clobbered.  We must not let a canonicalization do
618318334Speter	 anything in that case.  */
618418334Speter      for (i = 0; i < lim; i++)
618518334Speter	{
618618334Speter	  register rtx y = XVECEXP (x, 0, i);
618718334Speter	  if (GET_CODE (y) == CLOBBER)
618818334Speter	    {
618918334Speter	      rtx clobbered = XEXP (y, 0);
619018334Speter
619118334Speter	      if (GET_CODE (clobbered) == REG
619218334Speter		  || GET_CODE (clobbered) == SUBREG)
619318334Speter		invalidate (clobbered, VOIDmode);
619418334Speter	      else if (GET_CODE (clobbered) == STRICT_LOW_PART
619518334Speter		       || GET_CODE (clobbered) == ZERO_EXTRACT)
619618334Speter		invalidate (XEXP (clobbered, 0), GET_MODE (clobbered));
619718334Speter	    }
619818334Speter	}
619918334Speter
620018334Speter      for (i = 0; i < lim; i++)
620118334Speter	{
620218334Speter	  register rtx y = XVECEXP (x, 0, i);
620318334Speter	  if (GET_CODE (y) == SET)
620418334Speter	    {
620518334Speter	      /* As above, we ignore unconditional jumps and call-insns and
620618334Speter		 ignore the result of apply_change_group.  */
620718334Speter	      if (GET_CODE (SET_SRC (y)) == CALL)
620818334Speter		{
620918334Speter		  canon_reg (SET_SRC (y), insn);
621018334Speter		  apply_change_group ();
621118334Speter		  fold_rtx (SET_SRC (y), insn);
621218334Speter		  invalidate (SET_DEST (y), VOIDmode);
621318334Speter		}
621418334Speter	      else if (SET_DEST (y) == pc_rtx
621518334Speter		       && GET_CODE (SET_SRC (y)) == LABEL_REF)
621618334Speter		;
621718334Speter	      else
621818334Speter		sets[n_sets++].rtl = y;
621918334Speter	    }
622018334Speter	  else if (GET_CODE (y) == CLOBBER)
622118334Speter	    {
622218334Speter	      /* If we clobber memory, take note of that,
622318334Speter		 and canon the address.
622418334Speter		 This does nothing when a register is clobbered
622518334Speter		 because we have already invalidated the reg.  */
622618334Speter	      if (GET_CODE (XEXP (y, 0)) == MEM)
622718334Speter		{
622818334Speter		  canon_reg (XEXP (y, 0), NULL_RTX);
622918334Speter		  note_mem_written (XEXP (y, 0), &writes_memory);
623018334Speter		}
623118334Speter	    }
623218334Speter	  else if (GET_CODE (y) == USE
623318334Speter		   && ! (GET_CODE (XEXP (y, 0)) == REG
623418334Speter			 && REGNO (XEXP (y, 0)) < FIRST_PSEUDO_REGISTER))
623518334Speter	    canon_reg (y, NULL_RTX);
623618334Speter	  else if (GET_CODE (y) == CALL)
623718334Speter	    {
623818334Speter	      /* The result of apply_change_group can be ignored; see
623918334Speter		 canon_reg.  */
624018334Speter	      canon_reg (y, insn);
624118334Speter	      apply_change_group ();
624218334Speter	      fold_rtx (y, insn);
624318334Speter	    }
624418334Speter	}
624518334Speter    }
624618334Speter  else if (GET_CODE (x) == CLOBBER)
624718334Speter    {
624818334Speter      if (GET_CODE (XEXP (x, 0)) == MEM)
624918334Speter	{
625018334Speter	  canon_reg (XEXP (x, 0), NULL_RTX);
625118334Speter	  note_mem_written (XEXP (x, 0), &writes_memory);
625218334Speter	}
625318334Speter    }
625418334Speter
625518334Speter  /* Canonicalize a USE of a pseudo register or memory location.  */
625618334Speter  else if (GET_CODE (x) == USE
625718334Speter	   && ! (GET_CODE (XEXP (x, 0)) == REG
625818334Speter		 && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER))
625918334Speter    canon_reg (XEXP (x, 0), NULL_RTX);
626018334Speter  else if (GET_CODE (x) == CALL)
626118334Speter    {
626218334Speter      /* The result of apply_change_group can be ignored; see canon_reg.  */
626318334Speter      canon_reg (x, insn);
626418334Speter      apply_change_group ();
626518334Speter      fold_rtx (x, insn);
626618334Speter    }
626718334Speter
626818334Speter  /* Store the equivalent value in SRC_EQV, if different, or if the DEST
626918334Speter     is a STRICT_LOW_PART.  The latter condition is necessary because SRC_EQV
627018334Speter     is handled specially for this case, and if it isn't set, then there will
627118334Speter     be no equivalence for the destination.  */
627218334Speter  if (n_sets == 1 && REG_NOTES (insn) != 0
627318334Speter      && (tem = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0
627418334Speter      && (! rtx_equal_p (XEXP (tem, 0), SET_SRC (sets[0].rtl))
627518334Speter	  || GET_CODE (SET_DEST (sets[0].rtl)) == STRICT_LOW_PART))
627618334Speter    src_eqv = canon_reg (XEXP (tem, 0), NULL_RTX);
627718334Speter
627818334Speter  /* Canonicalize sources and addresses of destinations.
627918334Speter     We do this in a separate pass to avoid problems when a MATCH_DUP is
628018334Speter     present in the insn pattern.  In that case, we want to ensure that
628118334Speter     we don't break the duplicate nature of the pattern.  So we will replace
628218334Speter     both operands at the same time.  Otherwise, we would fail to find an
628318334Speter     equivalent substitution in the loop calling validate_change below.
628418334Speter
628518334Speter     We used to suppress canonicalization of DEST if it appears in SRC,
628618334Speter     but we don't do this any more.  */
628718334Speter
628818334Speter  for (i = 0; i < n_sets; i++)
628918334Speter    {
629018334Speter      rtx dest = SET_DEST (sets[i].rtl);
629118334Speter      rtx src = SET_SRC (sets[i].rtl);
629218334Speter      rtx new = canon_reg (src, insn);
629318334Speter
629418334Speter      if ((GET_CODE (new) == REG && GET_CODE (src) == REG
629518334Speter	   && ((REGNO (new) < FIRST_PSEUDO_REGISTER)
629618334Speter	       != (REGNO (src) < FIRST_PSEUDO_REGISTER)))
629718334Speter	  || insn_n_dups[recog_memoized (insn)] > 0)
629818334Speter	validate_change (insn, &SET_SRC (sets[i].rtl), new, 1);
629918334Speter      else
630018334Speter	SET_SRC (sets[i].rtl) = new;
630118334Speter
630218334Speter      if (GET_CODE (dest) == ZERO_EXTRACT || GET_CODE (dest) == SIGN_EXTRACT)
630318334Speter	{
630418334Speter	  validate_change (insn, &XEXP (dest, 1),
630518334Speter			   canon_reg (XEXP (dest, 1), insn), 1);
630618334Speter	  validate_change (insn, &XEXP (dest, 2),
630718334Speter			   canon_reg (XEXP (dest, 2), insn), 1);
630818334Speter	}
630918334Speter
631018334Speter      while (GET_CODE (dest) == SUBREG || GET_CODE (dest) == STRICT_LOW_PART
631118334Speter	     || GET_CODE (dest) == ZERO_EXTRACT
631218334Speter	     || GET_CODE (dest) == SIGN_EXTRACT)
631318334Speter	dest = XEXP (dest, 0);
631418334Speter
631518334Speter      if (GET_CODE (dest) == MEM)
631618334Speter	canon_reg (dest, insn);
631718334Speter    }
631818334Speter
631918334Speter  /* Now that we have done all the replacements, we can apply the change
632018334Speter     group and see if they all work.  Note that this will cause some
632118334Speter     canonicalizations that would have worked individually not to be applied
632218334Speter     because some other canonicalization didn't work, but this should not
632318334Speter     occur often.
632418334Speter
632518334Speter     The result of apply_change_group can be ignored; see canon_reg.  */
632618334Speter
632718334Speter  apply_change_group ();
632818334Speter
632918334Speter  /* Set sets[i].src_elt to the class each source belongs to.
633018334Speter     Detect assignments from or to volatile things
633118334Speter     and set set[i] to zero so they will be ignored
633218334Speter     in the rest of this function.
633318334Speter
633418334Speter     Nothing in this loop changes the hash table or the register chains.  */
633518334Speter
633618334Speter  for (i = 0; i < n_sets; i++)
633718334Speter    {
633818334Speter      register rtx src, dest;
633918334Speter      register rtx src_folded;
634018334Speter      register struct table_elt *elt = 0, *p;
634118334Speter      enum machine_mode mode;
634218334Speter      rtx src_eqv_here;
634318334Speter      rtx src_const = 0;
634418334Speter      rtx src_related = 0;
634518334Speter      struct table_elt *src_const_elt = 0;
634618334Speter      int src_cost = 10000, src_eqv_cost = 10000, src_folded_cost = 10000;
634718334Speter      int src_related_cost = 10000, src_elt_cost = 10000;
634818334Speter      /* Set non-zero if we need to call force_const_mem on with the
634918334Speter	 contents of src_folded before using it.  */
635018334Speter      int src_folded_force_flag = 0;
635118334Speter
635218334Speter      dest = SET_DEST (sets[i].rtl);
635318334Speter      src = SET_SRC (sets[i].rtl);
635418334Speter
635518334Speter      /* If SRC is a constant that has no machine mode,
635618334Speter	 hash it with the destination's machine mode.
635718334Speter	 This way we can keep different modes separate.  */
635818334Speter
635918334Speter      mode = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
636018334Speter      sets[i].mode = mode;
636118334Speter
636218334Speter      if (src_eqv)
636318334Speter	{
636418334Speter	  enum machine_mode eqvmode = mode;
636518334Speter	  if (GET_CODE (dest) == STRICT_LOW_PART)
636618334Speter	    eqvmode = GET_MODE (SUBREG_REG (XEXP (dest, 0)));
636718334Speter	  do_not_record = 0;
636818334Speter	  hash_arg_in_memory = 0;
636918334Speter	  hash_arg_in_struct = 0;
637018334Speter	  src_eqv = fold_rtx (src_eqv, insn);
637118334Speter	  src_eqv_hash = HASH (src_eqv, eqvmode);
637218334Speter
637318334Speter	  /* Find the equivalence class for the equivalent expression.  */
637418334Speter
637518334Speter	  if (!do_not_record)
637618334Speter	    src_eqv_elt = lookup (src_eqv, src_eqv_hash, eqvmode);
637718334Speter
637818334Speter	  src_eqv_volatile = do_not_record;
637918334Speter	  src_eqv_in_memory = hash_arg_in_memory;
638018334Speter	  src_eqv_in_struct = hash_arg_in_struct;
638118334Speter	}
638218334Speter
638318334Speter      /* If this is a STRICT_LOW_PART assignment, src_eqv corresponds to the
638418334Speter	 value of the INNER register, not the destination.  So it is not
638518334Speter	 a valid substitution for the source.  But save it for later.  */
638618334Speter      if (GET_CODE (dest) == STRICT_LOW_PART)
638718334Speter	src_eqv_here = 0;
638818334Speter      else
638918334Speter	src_eqv_here = src_eqv;
639018334Speter
639118334Speter      /* Simplify and foldable subexpressions in SRC.  Then get the fully-
639218334Speter	 simplified result, which may not necessarily be valid.  */
639318334Speter      src_folded = fold_rtx (src, insn);
639418334Speter
639518334Speter#if 0
639618334Speter      /* ??? This caused bad code to be generated for the m68k port with -O2.
639718334Speter	 Suppose src is (CONST_INT -1), and that after truncation src_folded
639818334Speter	 is (CONST_INT 3).  Suppose src_folded is then used for src_const.
639918334Speter	 At the end we will add src and src_const to the same equivalence
640018334Speter	 class.  We now have 3 and -1 on the same equivalence class.  This
640118334Speter	 causes later instructions to be mis-optimized.  */
640218334Speter      /* If storing a constant in a bitfield, pre-truncate the constant
640318334Speter	 so we will be able to record it later.  */
640418334Speter      if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT
640518334Speter	  || GET_CODE (SET_DEST (sets[i].rtl)) == SIGN_EXTRACT)
640618334Speter	{
640718334Speter	  rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
640818334Speter
640918334Speter	  if (GET_CODE (src) == CONST_INT
641018334Speter	      && GET_CODE (width) == CONST_INT
641118334Speter	      && INTVAL (width) < HOST_BITS_PER_WIDE_INT
641218334Speter	      && (INTVAL (src) & ((HOST_WIDE_INT) (-1) << INTVAL (width))))
641318334Speter	    src_folded
641418334Speter	      = GEN_INT (INTVAL (src) & (((HOST_WIDE_INT) 1
641518334Speter					  << INTVAL (width)) - 1));
641618334Speter	}
641718334Speter#endif
641818334Speter
641918334Speter      /* Compute SRC's hash code, and also notice if it
642018334Speter	 should not be recorded at all.  In that case,
642118334Speter	 prevent any further processing of this assignment.  */
642218334Speter      do_not_record = 0;
642318334Speter      hash_arg_in_memory = 0;
642418334Speter      hash_arg_in_struct = 0;
642518334Speter
642618334Speter      sets[i].src = src;
642718334Speter      sets[i].src_hash = HASH (src, mode);
642818334Speter      sets[i].src_volatile = do_not_record;
642918334Speter      sets[i].src_in_memory = hash_arg_in_memory;
643018334Speter      sets[i].src_in_struct = hash_arg_in_struct;
643118334Speter
643218334Speter#if 0
643318334Speter      /* It is no longer clear why we used to do this, but it doesn't
643418334Speter	 appear to still be needed.  So let's try without it since this
643518334Speter	 code hurts cse'ing widened ops.  */
643618334Speter      /* If source is a perverse subreg (such as QI treated as an SI),
643718334Speter	 treat it as volatile.  It may do the work of an SI in one context
643818334Speter	 where the extra bits are not being used, but cannot replace an SI
643918334Speter	 in general.  */
644018334Speter      if (GET_CODE (src) == SUBREG
644118334Speter	  && (GET_MODE_SIZE (GET_MODE (src))
644218334Speter	      > GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
644318334Speter	sets[i].src_volatile = 1;
644418334Speter#endif
644518334Speter
644618334Speter      /* Locate all possible equivalent forms for SRC.  Try to replace
644718334Speter         SRC in the insn with each cheaper equivalent.
644818334Speter
644918334Speter         We have the following types of equivalents: SRC itself, a folded
645018334Speter         version, a value given in a REG_EQUAL note, or a value related
645118334Speter	 to a constant.
645218334Speter
645318334Speter         Each of these equivalents may be part of an additional class
645418334Speter         of equivalents (if more than one is in the table, they must be in
645518334Speter         the same class; we check for this).
645618334Speter
645718334Speter	 If the source is volatile, we don't do any table lookups.
645818334Speter
645918334Speter         We note any constant equivalent for possible later use in a
646018334Speter         REG_NOTE.  */
646118334Speter
646218334Speter      if (!sets[i].src_volatile)
646318334Speter	elt = lookup (src, sets[i].src_hash, mode);
646418334Speter
646518334Speter      sets[i].src_elt = elt;
646618334Speter
646718334Speter      if (elt && src_eqv_here && src_eqv_elt)
646818334Speter        {
646918334Speter          if (elt->first_same_value != src_eqv_elt->first_same_value)
647018334Speter	    {
647118334Speter	      /* The REG_EQUAL is indicating that two formerly distinct
647218334Speter		 classes are now equivalent.  So merge them.  */
647318334Speter	      merge_equiv_classes (elt, src_eqv_elt);
647418334Speter	      src_eqv_hash = HASH (src_eqv, elt->mode);
647518334Speter	      src_eqv_elt = lookup (src_eqv, src_eqv_hash, elt->mode);
647618334Speter	    }
647718334Speter
647818334Speter          src_eqv_here = 0;
647918334Speter        }
648018334Speter
648118334Speter      else if (src_eqv_elt)
648218334Speter        elt = src_eqv_elt;
648318334Speter
648418334Speter      /* Try to find a constant somewhere and record it in `src_const'.
648518334Speter	 Record its table element, if any, in `src_const_elt'.  Look in
648618334Speter	 any known equivalences first.  (If the constant is not in the
648718334Speter	 table, also set `sets[i].src_const_hash').  */
648818334Speter      if (elt)
648918334Speter        for (p = elt->first_same_value; p; p = p->next_same_value)
649018334Speter	  if (p->is_const)
649118334Speter	    {
649218334Speter	      src_const = p->exp;
649318334Speter	      src_const_elt = elt;
649418334Speter	      break;
649518334Speter	    }
649618334Speter
649718334Speter      if (src_const == 0
649818334Speter	  && (CONSTANT_P (src_folded)
649918334Speter	      /* Consider (minus (label_ref L1) (label_ref L2)) as
650018334Speter		 "constant" here so we will record it. This allows us
650118334Speter		 to fold switch statements when an ADDR_DIFF_VEC is used.  */
650218334Speter	      || (GET_CODE (src_folded) == MINUS
650318334Speter		  && GET_CODE (XEXP (src_folded, 0)) == LABEL_REF
650418334Speter		  && GET_CODE (XEXP (src_folded, 1)) == LABEL_REF)))
650518334Speter	src_const = src_folded, src_const_elt = elt;
650618334Speter      else if (src_const == 0 && src_eqv_here && CONSTANT_P (src_eqv_here))
650718334Speter	src_const = src_eqv_here, src_const_elt = src_eqv_elt;
650818334Speter
650918334Speter      /* If we don't know if the constant is in the table, get its
651018334Speter	 hash code and look it up.  */
651118334Speter      if (src_const && src_const_elt == 0)
651218334Speter	{
651318334Speter	  sets[i].src_const_hash = HASH (src_const, mode);
651418334Speter	  src_const_elt = lookup (src_const, sets[i].src_const_hash, mode);
651518334Speter	}
651618334Speter
651718334Speter      sets[i].src_const = src_const;
651818334Speter      sets[i].src_const_elt = src_const_elt;
651918334Speter
652018334Speter      /* If the constant and our source are both in the table, mark them as
652118334Speter	 equivalent.  Otherwise, if a constant is in the table but the source
652218334Speter	 isn't, set ELT to it.  */
652318334Speter      if (src_const_elt && elt
652418334Speter	  && src_const_elt->first_same_value != elt->first_same_value)
652518334Speter	merge_equiv_classes (elt, src_const_elt);
652618334Speter      else if (src_const_elt && elt == 0)
652718334Speter	elt = src_const_elt;
652818334Speter
652918334Speter      /* See if there is a register linearly related to a constant
653018334Speter         equivalent of SRC.  */
653118334Speter      if (src_const
653218334Speter	  && (GET_CODE (src_const) == CONST
653318334Speter	      || (src_const_elt && src_const_elt->related_value != 0)))
653418334Speter        {
653518334Speter          src_related = use_related_value (src_const, src_const_elt);
653618334Speter          if (src_related)
653718334Speter            {
653818334Speter	      struct table_elt *src_related_elt
653918334Speter		    = lookup (src_related, HASH (src_related, mode), mode);
654018334Speter	      if (src_related_elt && elt)
654118334Speter	        {
654218334Speter		  if (elt->first_same_value
654318334Speter		      != src_related_elt->first_same_value)
654418334Speter		    /* This can occur when we previously saw a CONST
654518334Speter		       involving a SYMBOL_REF and then see the SYMBOL_REF
654618334Speter		       twice.  Merge the involved classes.  */
654718334Speter		    merge_equiv_classes (elt, src_related_elt);
654818334Speter
654918334Speter	          src_related = 0;
655018334Speter		  src_related_elt = 0;
655118334Speter	        }
655218334Speter              else if (src_related_elt && elt == 0)
655318334Speter	        elt = src_related_elt;
655418334Speter	    }
655518334Speter        }
655618334Speter
655718334Speter      /* See if we have a CONST_INT that is already in a register in a
655818334Speter	 wider mode.  */
655918334Speter
656018334Speter      if (src_const && src_related == 0 && GET_CODE (src_const) == CONST_INT
656118334Speter	  && GET_MODE_CLASS (mode) == MODE_INT
656218334Speter	  && GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
656318334Speter	{
656418334Speter	  enum machine_mode wider_mode;
656518334Speter
656618334Speter	  for (wider_mode = GET_MODE_WIDER_MODE (mode);
656718334Speter	       GET_MODE_BITSIZE (wider_mode) <= BITS_PER_WORD
656818334Speter	       && src_related == 0;
656918334Speter	       wider_mode = GET_MODE_WIDER_MODE (wider_mode))
657018334Speter	    {
657118334Speter	      struct table_elt *const_elt
657218334Speter		= lookup (src_const, HASH (src_const, wider_mode), wider_mode);
657318334Speter
657418334Speter	      if (const_elt == 0)
657518334Speter		continue;
657618334Speter
657718334Speter	      for (const_elt = const_elt->first_same_value;
657818334Speter		   const_elt; const_elt = const_elt->next_same_value)
657918334Speter		if (GET_CODE (const_elt->exp) == REG)
658018334Speter		  {
658118334Speter		    src_related = gen_lowpart_if_possible (mode,
658218334Speter							   const_elt->exp);
658318334Speter		    break;
658418334Speter		  }
658518334Speter	    }
658618334Speter	}
658718334Speter
658818334Speter      /* Another possibility is that we have an AND with a constant in
658918334Speter	 a mode narrower than a word.  If so, it might have been generated
659018334Speter	 as part of an "if" which would narrow the AND.  If we already
659118334Speter	 have done the AND in a wider mode, we can use a SUBREG of that
659218334Speter	 value.  */
659318334Speter
659418334Speter      if (flag_expensive_optimizations && ! src_related
659518334Speter	  && GET_CODE (src) == AND && GET_CODE (XEXP (src, 1)) == CONST_INT
659618334Speter	  && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
659718334Speter	{
659818334Speter	  enum machine_mode tmode;
659918334Speter	  rtx new_and = gen_rtx (AND, VOIDmode, NULL_RTX, XEXP (src, 1));
660018334Speter
660118334Speter	  for (tmode = GET_MODE_WIDER_MODE (mode);
660218334Speter	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
660318334Speter	       tmode = GET_MODE_WIDER_MODE (tmode))
660418334Speter	    {
660518334Speter	      rtx inner = gen_lowpart_if_possible (tmode, XEXP (src, 0));
660618334Speter	      struct table_elt *larger_elt;
660718334Speter
660818334Speter	      if (inner)
660918334Speter		{
661018334Speter		  PUT_MODE (new_and, tmode);
661118334Speter		  XEXP (new_and, 0) = inner;
661218334Speter		  larger_elt = lookup (new_and, HASH (new_and, tmode), tmode);
661318334Speter		  if (larger_elt == 0)
661418334Speter		    continue;
661518334Speter
661618334Speter		  for (larger_elt = larger_elt->first_same_value;
661718334Speter		       larger_elt; larger_elt = larger_elt->next_same_value)
661818334Speter		    if (GET_CODE (larger_elt->exp) == REG)
661918334Speter		      {
662018334Speter			src_related
662118334Speter			  = gen_lowpart_if_possible (mode, larger_elt->exp);
662218334Speter			break;
662318334Speter		      }
662418334Speter
662518334Speter		  if (src_related)
662618334Speter		    break;
662718334Speter		}
662818334Speter	    }
662918334Speter	}
663018334Speter
663118334Speter#ifdef LOAD_EXTEND_OP
663218334Speter      /* See if a MEM has already been loaded with a widening operation;
663318334Speter	 if it has, we can use a subreg of that.  Many CISC machines
663418334Speter	 also have such operations, but this is only likely to be
663518334Speter	 beneficial these machines.  */
663618334Speter
663718334Speter      if (flag_expensive_optimizations &&  src_related == 0
663818334Speter	  && (GET_MODE_SIZE (mode) < UNITS_PER_WORD)
663918334Speter	  && GET_MODE_CLASS (mode) == MODE_INT
664018334Speter	  && GET_CODE (src) == MEM && ! do_not_record
664118334Speter	  && LOAD_EXTEND_OP (mode) != NIL)
664218334Speter	{
664318334Speter	  enum machine_mode tmode;
664418334Speter
664518334Speter	  /* Set what we are trying to extend and the operation it might
664618334Speter	     have been extended with.  */
664718334Speter	  PUT_CODE (memory_extend_rtx, LOAD_EXTEND_OP (mode));
664818334Speter	  XEXP (memory_extend_rtx, 0) = src;
664918334Speter
665018334Speter	  for (tmode = GET_MODE_WIDER_MODE (mode);
665118334Speter	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
665218334Speter	       tmode = GET_MODE_WIDER_MODE (tmode))
665318334Speter	    {
665418334Speter	      struct table_elt *larger_elt;
665518334Speter
665618334Speter	      PUT_MODE (memory_extend_rtx, tmode);
665718334Speter	      larger_elt = lookup (memory_extend_rtx,
665818334Speter				   HASH (memory_extend_rtx, tmode), tmode);
665918334Speter	      if (larger_elt == 0)
666018334Speter		continue;
666118334Speter
666218334Speter	      for (larger_elt = larger_elt->first_same_value;
666318334Speter		   larger_elt; larger_elt = larger_elt->next_same_value)
666418334Speter		if (GET_CODE (larger_elt->exp) == REG)
666518334Speter		  {
666618334Speter		    src_related = gen_lowpart_if_possible (mode,
666718334Speter							   larger_elt->exp);
666818334Speter		    break;
666918334Speter		  }
667018334Speter
667118334Speter	      if (src_related)
667218334Speter		break;
667318334Speter	    }
667418334Speter	}
667518334Speter#endif /* LOAD_EXTEND_OP */
667618334Speter
667718334Speter      if (src == src_folded)
667818334Speter        src_folded = 0;
667918334Speter
668018334Speter      /* At this point, ELT, if non-zero, points to a class of expressions
668118334Speter         equivalent to the source of this SET and SRC, SRC_EQV, SRC_FOLDED,
668218334Speter	 and SRC_RELATED, if non-zero, each contain additional equivalent
668318334Speter	 expressions.  Prune these latter expressions by deleting expressions
668418334Speter	 already in the equivalence class.
668518334Speter
668618334Speter	 Check for an equivalent identical to the destination.  If found,
668718334Speter	 this is the preferred equivalent since it will likely lead to
668818334Speter	 elimination of the insn.  Indicate this by placing it in
668918334Speter	 `src_related'.  */
669018334Speter
669118334Speter      if (elt) elt = elt->first_same_value;
669218334Speter      for (p = elt; p; p = p->next_same_value)
669318334Speter        {
669418334Speter	  enum rtx_code code = GET_CODE (p->exp);
669518334Speter
669618334Speter	  /* If the expression is not valid, ignore it.  Then we do not
669718334Speter	     have to check for validity below.  In most cases, we can use
669818334Speter	     `rtx_equal_p', since canonicalization has already been done.  */
669918334Speter	  if (code != REG && ! exp_equiv_p (p->exp, p->exp, 1, 0))
670018334Speter	    continue;
670118334Speter
670218334Speter          if (src && GET_CODE (src) == code && rtx_equal_p (src, p->exp))
670318334Speter	    src = 0;
670418334Speter          else if (src_folded && GET_CODE (src_folded) == code
670518334Speter		   && rtx_equal_p (src_folded, p->exp))
670618334Speter	    src_folded = 0;
670718334Speter          else if (src_eqv_here && GET_CODE (src_eqv_here) == code
670818334Speter		   && rtx_equal_p (src_eqv_here, p->exp))
670918334Speter	    src_eqv_here = 0;
671018334Speter          else if (src_related && GET_CODE (src_related) == code
671118334Speter		   && rtx_equal_p (src_related, p->exp))
671218334Speter	    src_related = 0;
671318334Speter
671418334Speter	  /* This is the same as the destination of the insns, we want
671518334Speter	     to prefer it.  Copy it to src_related.  The code below will
671618334Speter	     then give it a negative cost.  */
671718334Speter	  if (GET_CODE (dest) == code && rtx_equal_p (p->exp, dest))
671818334Speter	    src_related = dest;
671918334Speter
672018334Speter        }
672118334Speter
672218334Speter      /* Find the cheapest valid equivalent, trying all the available
672318334Speter         possibilities.  Prefer items not in the hash table to ones
672418334Speter         that are when they are equal cost.  Note that we can never
672518334Speter         worsen an insn as the current contents will also succeed.
672618334Speter	 If we find an equivalent identical to the destination, use it as best,
672718334Speter	 since this insn will probably be eliminated in that case. */
672818334Speter      if (src)
672918334Speter	{
673018334Speter	  if (rtx_equal_p (src, dest))
673118334Speter	    src_cost = -1;
673218334Speter	  else
673318334Speter	    src_cost = COST (src);
673418334Speter	}
673518334Speter
673618334Speter      if (src_eqv_here)
673718334Speter	{
673818334Speter	  if (rtx_equal_p (src_eqv_here, dest))
673918334Speter	    src_eqv_cost = -1;
674018334Speter	  else
674118334Speter	    src_eqv_cost = COST (src_eqv_here);
674218334Speter	}
674318334Speter
674418334Speter      if (src_folded)
674518334Speter	{
674618334Speter	  if (rtx_equal_p (src_folded, dest))
674718334Speter	    src_folded_cost = -1;
674818334Speter	  else
674918334Speter	    src_folded_cost = COST (src_folded);
675018334Speter	}
675118334Speter
675218334Speter      if (src_related)
675318334Speter	{
675418334Speter	  if (rtx_equal_p (src_related, dest))
675518334Speter	    src_related_cost = -1;
675618334Speter	  else
675718334Speter	    src_related_cost = COST (src_related);
675818334Speter	}
675918334Speter
676018334Speter      /* If this was an indirect jump insn, a known label will really be
676118334Speter	 cheaper even though it looks more expensive.  */
676218334Speter      if (dest == pc_rtx && src_const && GET_CODE (src_const) == LABEL_REF)
676318334Speter	src_folded = src_const, src_folded_cost = -1;
676418334Speter
676518334Speter      /* Terminate loop when replacement made.  This must terminate since
676618334Speter         the current contents will be tested and will always be valid.  */
676718334Speter      while (1)
676818334Speter        {
676918334Speter          rtx trial;
677018334Speter
677118334Speter          /* Skip invalid entries.  */
677218334Speter          while (elt && GET_CODE (elt->exp) != REG
677318334Speter	         && ! exp_equiv_p (elt->exp, elt->exp, 1, 0))
677418334Speter	    elt = elt->next_same_value;
677518334Speter
677618334Speter          if (elt) src_elt_cost = elt->cost;
677718334Speter
677818334Speter          /* Find cheapest and skip it for the next time.   For items
677918334Speter	     of equal cost, use this order:
678018334Speter	     src_folded, src, src_eqv, src_related and hash table entry.  */
678118334Speter          if (src_folded_cost <= src_cost
678218334Speter	      && src_folded_cost <= src_eqv_cost
678318334Speter	      && src_folded_cost <= src_related_cost
678418334Speter	      && src_folded_cost <= src_elt_cost)
678518334Speter	    {
678618334Speter	      trial = src_folded, src_folded_cost = 10000;
678718334Speter	      if (src_folded_force_flag)
678818334Speter		trial = force_const_mem (mode, trial);
678918334Speter	    }
679018334Speter          else if (src_cost <= src_eqv_cost
679118334Speter	           && src_cost <= src_related_cost
679218334Speter	           && src_cost <= src_elt_cost)
679318334Speter	    trial = src, src_cost = 10000;
679418334Speter          else if (src_eqv_cost <= src_related_cost
679518334Speter	           && src_eqv_cost <= src_elt_cost)
679618334Speter	    trial = copy_rtx (src_eqv_here), src_eqv_cost = 10000;
679718334Speter          else if (src_related_cost <= src_elt_cost)
679818334Speter	    trial = copy_rtx (src_related), src_related_cost = 10000;
679918334Speter          else
680018334Speter	    {
680118334Speter	      trial = copy_rtx (elt->exp);
680218334Speter	      elt = elt->next_same_value;
680318334Speter	      src_elt_cost = 10000;
680418334Speter	    }
680518334Speter
680618334Speter	  /* We don't normally have an insn matching (set (pc) (pc)), so
680718334Speter	     check for this separately here.  We will delete such an
680818334Speter	     insn below.
680918334Speter
681018334Speter	     Tablejump insns contain a USE of the table, so simply replacing
681118334Speter	     the operand with the constant won't match.  This is simply an
681218334Speter	     unconditional branch, however, and is therefore valid.  Just
681318334Speter	     insert the substitution here and we will delete and re-emit
681418334Speter	     the insn later.  */
681518334Speter
681618334Speter	  if (n_sets == 1 && dest == pc_rtx
681718334Speter	      && (trial == pc_rtx
681818334Speter		  || (GET_CODE (trial) == LABEL_REF
681918334Speter		      && ! condjump_p (insn))))
682018334Speter	    {
682118334Speter	      /* If TRIAL is a label in front of a jump table, we are
682218334Speter		 really falling through the switch (this is how casesi
682318334Speter		 insns work), so we must branch around the table.  */
682418334Speter	      if (GET_CODE (trial) == CODE_LABEL
682518334Speter		  && NEXT_INSN (trial) != 0
682618334Speter		  && GET_CODE (NEXT_INSN (trial)) == JUMP_INSN
682718334Speter		  && (GET_CODE (PATTERN (NEXT_INSN (trial))) == ADDR_DIFF_VEC
682818334Speter		      || GET_CODE (PATTERN (NEXT_INSN (trial))) == ADDR_VEC))
682918334Speter
683018334Speter		trial = gen_rtx (LABEL_REF, Pmode, get_label_after (trial));
683118334Speter
683218334Speter	      SET_SRC (sets[i].rtl) = trial;
683318334Speter 	      cse_jumps_altered = 1;
683418334Speter	      break;
683518334Speter	    }
683618334Speter
683718334Speter	  /* Look for a substitution that makes a valid insn.  */
683818334Speter          else if (validate_change (insn, &SET_SRC (sets[i].rtl), trial, 0))
683918334Speter	    {
684018334Speter	      /* The result of apply_change_group can be ignored; see
684118334Speter		 canon_reg.  */
684218334Speter
684318334Speter	      validate_change (insn, &SET_SRC (sets[i].rtl),
684418334Speter			       canon_reg (SET_SRC (sets[i].rtl), insn),
684518334Speter			       1);
684618334Speter	      apply_change_group ();
684718334Speter	      break;
684818334Speter	    }
684918334Speter
685018334Speter	  /* If we previously found constant pool entries for
685118334Speter	     constants and this is a constant, try making a
685218334Speter	     pool entry.  Put it in src_folded unless we already have done
685318334Speter	     this since that is where it likely came from.  */
685418334Speter
685518334Speter	  else if (constant_pool_entries_cost
685618334Speter		   && CONSTANT_P (trial)
685718334Speter		   && ! (GET_CODE (trial) == CONST
685818334Speter			 && GET_CODE (XEXP (trial, 0)) == TRUNCATE)
685918334Speter		   && (src_folded == 0
686018334Speter		       || (GET_CODE (src_folded) != MEM
686118334Speter			   && ! src_folded_force_flag))
686218334Speter		   && GET_MODE_CLASS (mode) != MODE_CC)
686318334Speter	    {
686418334Speter	      src_folded_force_flag = 1;
686518334Speter	      src_folded = trial;
686618334Speter	      src_folded_cost = constant_pool_entries_cost;
686718334Speter	    }
686818334Speter        }
686918334Speter
687018334Speter      src = SET_SRC (sets[i].rtl);
687118334Speter
687218334Speter      /* In general, it is good to have a SET with SET_SRC == SET_DEST.
687318334Speter	 However, there is an important exception:  If both are registers
687418334Speter	 that are not the head of their equivalence class, replace SET_SRC
687518334Speter	 with the head of the class.  If we do not do this, we will have
687618334Speter	 both registers live over a portion of the basic block.  This way,
687718334Speter	 their lifetimes will likely abut instead of overlapping.  */
687818334Speter      if (GET_CODE (dest) == REG
687918334Speter	  && REGNO_QTY_VALID_P (REGNO (dest))
688018334Speter	  && qty_mode[reg_qty[REGNO (dest)]] == GET_MODE (dest)
688118334Speter	  && qty_first_reg[reg_qty[REGNO (dest)]] != REGNO (dest)
688218334Speter	  && GET_CODE (src) == REG && REGNO (src) == REGNO (dest)
688318334Speter	  /* Don't do this if the original insn had a hard reg as
688418334Speter	     SET_SRC.  */
688518334Speter	  && (GET_CODE (sets[i].src) != REG
688618334Speter	      || REGNO (sets[i].src) >= FIRST_PSEUDO_REGISTER))
688718334Speter	/* We can't call canon_reg here because it won't do anything if
688818334Speter	   SRC is a hard register.  */
688918334Speter	{
689018334Speter	  int first = qty_first_reg[reg_qty[REGNO (src)]];
689118334Speter
689218334Speter	  src = SET_SRC (sets[i].rtl)
689318334Speter	    = first >= FIRST_PSEUDO_REGISTER ? regno_reg_rtx[first]
689418334Speter	      : gen_rtx (REG, GET_MODE (src), first);
689518334Speter
689618334Speter	  /* If we had a constant that is cheaper than what we are now
689718334Speter	     setting SRC to, use that constant.  We ignored it when we
689818334Speter	     thought we could make this into a no-op.  */
689918334Speter	  if (src_const && COST (src_const) < COST (src)
690018334Speter	      && validate_change (insn, &SET_SRC (sets[i].rtl), src_const, 0))
690118334Speter	    src = src_const;
690218334Speter	}
690318334Speter
690418334Speter      /* If we made a change, recompute SRC values.  */
690518334Speter      if (src != sets[i].src)
690618334Speter        {
690718334Speter          do_not_record = 0;
690818334Speter          hash_arg_in_memory = 0;
690918334Speter          hash_arg_in_struct = 0;
691018334Speter	  sets[i].src = src;
691118334Speter          sets[i].src_hash = HASH (src, mode);
691218334Speter          sets[i].src_volatile = do_not_record;
691318334Speter          sets[i].src_in_memory = hash_arg_in_memory;
691418334Speter          sets[i].src_in_struct = hash_arg_in_struct;
691518334Speter          sets[i].src_elt = lookup (src, sets[i].src_hash, mode);
691618334Speter        }
691718334Speter
691818334Speter      /* If this is a single SET, we are setting a register, and we have an
691918334Speter	 equivalent constant, we want to add a REG_NOTE.   We don't want
692018334Speter	 to write a REG_EQUAL note for a constant pseudo since verifying that
692118334Speter	 that pseudo hasn't been eliminated is a pain.  Such a note also
692218334Speter	 won't help anything.  */
692318334Speter      if (n_sets == 1 && src_const && GET_CODE (dest) == REG
692418334Speter	  && GET_CODE (src_const) != REG)
692518334Speter	{
692618334Speter	  tem = find_reg_note (insn, REG_EQUAL, NULL_RTX);
692718334Speter
692818334Speter	  /* Record the actual constant value in a REG_EQUAL note, making
692918334Speter	     a new one if one does not already exist.  */
693018334Speter	  if (tem)
693118334Speter	    XEXP (tem, 0) = src_const;
693218334Speter	  else
693318334Speter	    REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL,
693418334Speter				        src_const, REG_NOTES (insn));
693518334Speter
693618334Speter          /* If storing a constant value in a register that
693718334Speter	     previously held the constant value 0,
693818334Speter	     record this fact with a REG_WAS_0 note on this insn.
693918334Speter
694018334Speter	     Note that the *register* is required to have previously held 0,
694118334Speter	     not just any register in the quantity and we must point to the
694218334Speter	     insn that set that register to zero.
694318334Speter
694418334Speter	     Rather than track each register individually, we just see if
694518334Speter	     the last set for this quantity was for this register.  */
694618334Speter
694718334Speter	  if (REGNO_QTY_VALID_P (REGNO (dest))
694818334Speter	      && qty_const[reg_qty[REGNO (dest)]] == const0_rtx)
694918334Speter	    {
695018334Speter	      /* See if we previously had a REG_WAS_0 note.  */
695118334Speter	      rtx note = find_reg_note (insn, REG_WAS_0, NULL_RTX);
695218334Speter	      rtx const_insn = qty_const_insn[reg_qty[REGNO (dest)]];
695318334Speter
695418334Speter	      if ((tem = single_set (const_insn)) != 0
695518334Speter		  && rtx_equal_p (SET_DEST (tem), dest))
695618334Speter		{
695718334Speter		  if (note)
695818334Speter		    XEXP (note, 0) = const_insn;
695918334Speter		  else
696018334Speter		    REG_NOTES (insn) = gen_rtx (INSN_LIST, REG_WAS_0,
696118334Speter						const_insn, REG_NOTES (insn));
696218334Speter		}
696318334Speter	    }
696418334Speter	}
696518334Speter
696618334Speter      /* Now deal with the destination.  */
696718334Speter      do_not_record = 0;
696818334Speter      sets[i].inner_dest_loc = &SET_DEST (sets[0].rtl);
696918334Speter
697018334Speter      /* Look within any SIGN_EXTRACT or ZERO_EXTRACT
697118334Speter	 to the MEM or REG within it.  */
697218334Speter      while (GET_CODE (dest) == SIGN_EXTRACT
697318334Speter	     || GET_CODE (dest) == ZERO_EXTRACT
697418334Speter	     || GET_CODE (dest) == SUBREG
697518334Speter	     || GET_CODE (dest) == STRICT_LOW_PART)
697618334Speter	{
697718334Speter	  sets[i].inner_dest_loc = &XEXP (dest, 0);
697818334Speter	  dest = XEXP (dest, 0);
697918334Speter	}
698018334Speter
698118334Speter      sets[i].inner_dest = dest;
698218334Speter
698318334Speter      if (GET_CODE (dest) == MEM)
698418334Speter	{
698518334Speter	  dest = fold_rtx (dest, insn);
698618334Speter
698718334Speter	  /* Decide whether we invalidate everything in memory,
698818334Speter	     or just things at non-fixed places.
698918334Speter	     Writing a large aggregate must invalidate everything
699018334Speter	     because we don't know how long it is.  */
699118334Speter	  note_mem_written (dest, &writes_memory);
699218334Speter	}
699318334Speter
699418334Speter      /* Compute the hash code of the destination now,
699518334Speter	 before the effects of this instruction are recorded,
699618334Speter	 since the register values used in the address computation
699718334Speter	 are those before this instruction.  */
699818334Speter      sets[i].dest_hash = HASH (dest, mode);
699918334Speter
700018334Speter      /* Don't enter a bit-field in the hash table
700118334Speter	 because the value in it after the store
700218334Speter	 may not equal what was stored, due to truncation.  */
700318334Speter
700418334Speter      if (GET_CODE (SET_DEST (sets[i].rtl)) == ZERO_EXTRACT
700518334Speter	  || GET_CODE (SET_DEST (sets[i].rtl)) == SIGN_EXTRACT)
700618334Speter	{
700718334Speter	  rtx width = XEXP (SET_DEST (sets[i].rtl), 1);
700818334Speter
700918334Speter	  if (src_const != 0 && GET_CODE (src_const) == CONST_INT
701018334Speter	      && GET_CODE (width) == CONST_INT
701118334Speter	      && INTVAL (width) < HOST_BITS_PER_WIDE_INT
701218334Speter	      && ! (INTVAL (src_const)
701318334Speter		    & ((HOST_WIDE_INT) (-1) << INTVAL (width))))
701418334Speter	    /* Exception: if the value is constant,
701518334Speter	       and it won't be truncated, record it.  */
701618334Speter	    ;
701718334Speter	  else
701818334Speter	    {
701918334Speter	      /* This is chosen so that the destination will be invalidated
702018334Speter		 but no new value will be recorded.
702118334Speter		 We must invalidate because sometimes constant
702218334Speter		 values can be recorded for bitfields.  */
702318334Speter	      sets[i].src_elt = 0;
702418334Speter	      sets[i].src_volatile = 1;
702518334Speter	      src_eqv = 0;
702618334Speter	      src_eqv_elt = 0;
702718334Speter	    }
702818334Speter	}
702918334Speter
703018334Speter      /* If only one set in a JUMP_INSN and it is now a no-op, we can delete
703118334Speter	 the insn.  */
703218334Speter      else if (n_sets == 1 && dest == pc_rtx && src == pc_rtx)
703318334Speter	{
703418334Speter	  PUT_CODE (insn, NOTE);
703518334Speter	  NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
703618334Speter	  NOTE_SOURCE_FILE (insn) = 0;
703718334Speter	  cse_jumps_altered = 1;
703818334Speter	  /* One less use of the label this insn used to jump to.  */
703918334Speter	  --LABEL_NUSES (JUMP_LABEL (insn));
704018334Speter	  /* No more processing for this set.  */
704118334Speter	  sets[i].rtl = 0;
704218334Speter	}
704318334Speter
704418334Speter      /* If this SET is now setting PC to a label, we know it used to
704518334Speter	 be a conditional or computed branch.  So we see if we can follow
704618334Speter	 it.  If it was a computed branch, delete it and re-emit.  */
704718334Speter      else if (dest == pc_rtx && GET_CODE (src) == LABEL_REF)
704818334Speter	{
704918334Speter	  rtx p;
705018334Speter
705118334Speter	  /* If this is not in the format for a simple branch and
705218334Speter	     we are the only SET in it, re-emit it.  */
705318334Speter	  if (! simplejump_p (insn) && n_sets == 1)
705418334Speter	    {
705518334Speter	      rtx new = emit_jump_insn_before (gen_jump (XEXP (src, 0)), insn);
705618334Speter	      JUMP_LABEL (new) = XEXP (src, 0);
705718334Speter	      LABEL_NUSES (XEXP (src, 0))++;
705818334Speter	      delete_insn (insn);
705918334Speter	      insn = new;
706018334Speter	    }
706118334Speter	  else
706218334Speter	    /* Otherwise, force rerecognition, since it probably had
706318334Speter	       a different pattern before.
706418334Speter	       This shouldn't really be necessary, since whatever
706518334Speter	       changed the source value above should have done this.
706618334Speter	       Until the right place is found, might as well do this here.  */
706718334Speter	    INSN_CODE (insn) = -1;
706818334Speter
706918334Speter	  /* Now that we've converted this jump to an unconditional jump,
707018334Speter	     there is dead code after it.  Delete the dead code until we
707118334Speter	     reach a BARRIER, the end of the function, or a label.  Do
707218334Speter	     not delete NOTEs except for NOTE_INSN_DELETED since later
707318334Speter	     phases assume these notes are retained.  */
707418334Speter
707518334Speter	  p = insn;
707618334Speter
707718334Speter	  while (NEXT_INSN (p) != 0
707818334Speter		 && GET_CODE (NEXT_INSN (p)) != BARRIER
707918334Speter		 && GET_CODE (NEXT_INSN (p)) != CODE_LABEL)
708018334Speter	    {
708118334Speter	      if (GET_CODE (NEXT_INSN (p)) != NOTE
708218334Speter		  || NOTE_LINE_NUMBER (NEXT_INSN (p)) == NOTE_INSN_DELETED)
708318334Speter		delete_insn (NEXT_INSN (p));
708418334Speter	      else
708518334Speter		p = NEXT_INSN (p);
708618334Speter	    }
708718334Speter
708818334Speter	  /* If we don't have a BARRIER immediately after INSN, put one there.
708918334Speter	     Much code assumes that there are no NOTEs between a JUMP_INSN and
709018334Speter	     BARRIER.  */
709118334Speter
709218334Speter	  if (NEXT_INSN (insn) == 0
709318334Speter	      || GET_CODE (NEXT_INSN (insn)) != BARRIER)
709418334Speter	    emit_barrier_before (NEXT_INSN (insn));
709518334Speter
709618334Speter	  /* We might have two BARRIERs separated by notes.  Delete the second
709718334Speter	     one if so.  */
709818334Speter
709918334Speter	  if (p != insn && NEXT_INSN (p) != 0
710018334Speter	      && GET_CODE (NEXT_INSN (p)) == BARRIER)
710118334Speter	    delete_insn (NEXT_INSN (p));
710218334Speter
710318334Speter	  cse_jumps_altered = 1;
710418334Speter	  sets[i].rtl = 0;
710518334Speter	}
710618334Speter
710718334Speter      /* If destination is volatile, invalidate it and then do no further
710818334Speter	 processing for this assignment.  */
710918334Speter
711018334Speter      else if (do_not_record)
711118334Speter	{
711218334Speter	  if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
711318334Speter	      || GET_CODE (dest) == MEM)
711418334Speter	    invalidate (dest, VOIDmode);
711518334Speter	  else if (GET_CODE (dest) == STRICT_LOW_PART
711618334Speter		   || GET_CODE (dest) == ZERO_EXTRACT)
711718334Speter	    invalidate (XEXP (dest, 0), GET_MODE (dest));
711818334Speter	  sets[i].rtl = 0;
711918334Speter	}
712018334Speter
712118334Speter      if (sets[i].rtl != 0 && dest != SET_DEST (sets[i].rtl))
712218334Speter	sets[i].dest_hash = HASH (SET_DEST (sets[i].rtl), mode);
712318334Speter
712418334Speter#ifdef HAVE_cc0
712518334Speter      /* If setting CC0, record what it was set to, or a constant, if it
712618334Speter	 is equivalent to a constant.  If it is being set to a floating-point
712718334Speter	 value, make a COMPARE with the appropriate constant of 0.  If we
712818334Speter	 don't do this, later code can interpret this as a test against
712918334Speter	 const0_rtx, which can cause problems if we try to put it into an
713018334Speter	 insn as a floating-point operand.  */
713118334Speter      if (dest == cc0_rtx)
713218334Speter	{
713318334Speter	  this_insn_cc0 = src_const && mode != VOIDmode ? src_const : src;
713418334Speter	  this_insn_cc0_mode = mode;
713518334Speter	  if (FLOAT_MODE_P (mode))
713618334Speter	    this_insn_cc0 = gen_rtx (COMPARE, VOIDmode, this_insn_cc0,
713718334Speter				     CONST0_RTX (mode));
713818334Speter	}
713918334Speter#endif
714018334Speter    }
714118334Speter
714218334Speter  /* Now enter all non-volatile source expressions in the hash table
714318334Speter     if they are not already present.
714418334Speter     Record their equivalence classes in src_elt.
714518334Speter     This way we can insert the corresponding destinations into
714618334Speter     the same classes even if the actual sources are no longer in them
714718334Speter     (having been invalidated).  */
714818334Speter
714918334Speter  if (src_eqv && src_eqv_elt == 0 && sets[0].rtl != 0 && ! src_eqv_volatile
715018334Speter      && ! rtx_equal_p (src_eqv, SET_DEST (sets[0].rtl)))
715118334Speter    {
715218334Speter      register struct table_elt *elt;
715318334Speter      register struct table_elt *classp = sets[0].src_elt;
715418334Speter      rtx dest = SET_DEST (sets[0].rtl);
715518334Speter      enum machine_mode eqvmode = GET_MODE (dest);
715618334Speter
715718334Speter      if (GET_CODE (dest) == STRICT_LOW_PART)
715818334Speter	{
715918334Speter	  eqvmode = GET_MODE (SUBREG_REG (XEXP (dest, 0)));
716018334Speter	  classp = 0;
716118334Speter	}
716218334Speter      if (insert_regs (src_eqv, classp, 0))
716318334Speter	{
716418334Speter	  rehash_using_reg (src_eqv);
716518334Speter	  src_eqv_hash = HASH (src_eqv, eqvmode);
716618334Speter	}
716718334Speter      elt = insert (src_eqv, classp, src_eqv_hash, eqvmode);
716818334Speter      elt->in_memory = src_eqv_in_memory;
716918334Speter      elt->in_struct = src_eqv_in_struct;
717018334Speter      src_eqv_elt = elt;
717118334Speter
717218334Speter      /* Check to see if src_eqv_elt is the same as a set source which
717318334Speter	 does not yet have an elt, and if so set the elt of the set source
717418334Speter	 to src_eqv_elt.  */
717518334Speter      for (i = 0; i < n_sets; i++)
717618334Speter	if (sets[i].rtl && sets[i].src_elt == 0
717718334Speter	    && rtx_equal_p (SET_SRC (sets[i].rtl), src_eqv))
717818334Speter	  sets[i].src_elt = src_eqv_elt;
717918334Speter    }
718018334Speter
718118334Speter  for (i = 0; i < n_sets; i++)
718218334Speter    if (sets[i].rtl && ! sets[i].src_volatile
718318334Speter	&& ! rtx_equal_p (SET_SRC (sets[i].rtl), SET_DEST (sets[i].rtl)))
718418334Speter      {
718518334Speter	if (GET_CODE (SET_DEST (sets[i].rtl)) == STRICT_LOW_PART)
718618334Speter	  {
718718334Speter	    /* REG_EQUAL in setting a STRICT_LOW_PART
718818334Speter	       gives an equivalent for the entire destination register,
718918334Speter	       not just for the subreg being stored in now.
719018334Speter	       This is a more interesting equivalence, so we arrange later
719118334Speter	       to treat the entire reg as the destination.  */
719218334Speter	    sets[i].src_elt = src_eqv_elt;
719318334Speter	    sets[i].src_hash = src_eqv_hash;
719418334Speter	  }
719518334Speter	else
719618334Speter	  {
719718334Speter	    /* Insert source and constant equivalent into hash table, if not
719818334Speter	       already present.  */
719918334Speter	    register struct table_elt *classp = src_eqv_elt;
720018334Speter	    register rtx src = sets[i].src;
720118334Speter	    register rtx dest = SET_DEST (sets[i].rtl);
720218334Speter	    enum machine_mode mode
720318334Speter	      = GET_MODE (src) == VOIDmode ? GET_MODE (dest) : GET_MODE (src);
720418334Speter
720518334Speter	    if (sets[i].src_elt == 0)
720618334Speter	      {
720718334Speter		register struct table_elt *elt;
720818334Speter
720918334Speter		/* Note that these insert_regs calls cannot remove
721018334Speter		   any of the src_elt's, because they would have failed to
721118334Speter		   match if not still valid.  */
721218334Speter		if (insert_regs (src, classp, 0))
721318334Speter		  {
721418334Speter		    rehash_using_reg (src);
721518334Speter		    sets[i].src_hash = HASH (src, mode);
721618334Speter		  }
721718334Speter		elt = insert (src, classp, sets[i].src_hash, mode);
721818334Speter		elt->in_memory = sets[i].src_in_memory;
721918334Speter		elt->in_struct = sets[i].src_in_struct;
722018334Speter		sets[i].src_elt = classp = elt;
722118334Speter	      }
722218334Speter
722318334Speter	    if (sets[i].src_const && sets[i].src_const_elt == 0
722418334Speter		&& src != sets[i].src_const
722518334Speter		&& ! rtx_equal_p (sets[i].src_const, src))
722618334Speter	      sets[i].src_elt = insert (sets[i].src_const, classp,
722718334Speter					sets[i].src_const_hash, mode);
722818334Speter	  }
722918334Speter      }
723018334Speter    else if (sets[i].src_elt == 0)
723118334Speter      /* If we did not insert the source into the hash table (e.g., it was
723218334Speter	 volatile), note the equivalence class for the REG_EQUAL value, if any,
723318334Speter	 so that the destination goes into that class.  */
723418334Speter      sets[i].src_elt = src_eqv_elt;
723518334Speter
723618334Speter  invalidate_from_clobbers (&writes_memory, x);
723718334Speter
723818334Speter  /* Some registers are invalidated by subroutine calls.  Memory is
723918334Speter     invalidated by non-constant calls.  */
724018334Speter
724118334Speter  if (GET_CODE (insn) == CALL_INSN)
724218334Speter    {
724318334Speter      static struct write_data everything = {0, 1, 1, 1};
724418334Speter
724518334Speter      if (! CONST_CALL_P (insn))
724618334Speter	invalidate_memory (&everything);
724718334Speter      invalidate_for_call ();
724818334Speter    }
724918334Speter
725018334Speter  /* Now invalidate everything set by this instruction.
725118334Speter     If a SUBREG or other funny destination is being set,
725218334Speter     sets[i].rtl is still nonzero, so here we invalidate the reg
725318334Speter     a part of which is being set.  */
725418334Speter
725518334Speter  for (i = 0; i < n_sets; i++)
725618334Speter    if (sets[i].rtl)
725718334Speter      {
725818334Speter	/* We can't use the inner dest, because the mode associated with
725918334Speter	   a ZERO_EXTRACT is significant.  */
726018334Speter	register rtx dest = SET_DEST (sets[i].rtl);
726118334Speter
726218334Speter	/* Needed for registers to remove the register from its
726318334Speter	   previous quantity's chain.
726418334Speter	   Needed for memory if this is a nonvarying address, unless
726518334Speter	   we have just done an invalidate_memory that covers even those.  */
726618334Speter	if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
726718334Speter	    || (GET_CODE (dest) == MEM && ! writes_memory.all
726818334Speter		&& ! cse_rtx_addr_varies_p (dest)))
726918334Speter	  invalidate (dest, VOIDmode);
727018334Speter	else if (GET_CODE (dest) == STRICT_LOW_PART
727118334Speter		 || GET_CODE (dest) == ZERO_EXTRACT)
727218334Speter	  invalidate (XEXP (dest, 0), GET_MODE (dest));
727318334Speter      }
727418334Speter
727518334Speter  /* Make sure registers mentioned in destinations
727618334Speter     are safe for use in an expression to be inserted.
727718334Speter     This removes from the hash table
727818334Speter     any invalid entry that refers to one of these registers.
727918334Speter
728018334Speter     We don't care about the return value from mention_regs because
728118334Speter     we are going to hash the SET_DEST values unconditionally.  */
728218334Speter
728318334Speter  for (i = 0; i < n_sets; i++)
728418334Speter    if (sets[i].rtl && GET_CODE (SET_DEST (sets[i].rtl)) != REG)
728518334Speter      mention_regs (SET_DEST (sets[i].rtl));
728618334Speter
728718334Speter  /* We may have just removed some of the src_elt's from the hash table.
728818334Speter     So replace each one with the current head of the same class.  */
728918334Speter
729018334Speter  for (i = 0; i < n_sets; i++)
729118334Speter    if (sets[i].rtl)
729218334Speter      {
729318334Speter	if (sets[i].src_elt && sets[i].src_elt->first_same_value == 0)
729418334Speter	  /* If elt was removed, find current head of same class,
729518334Speter	     or 0 if nothing remains of that class.  */
729618334Speter	  {
729718334Speter	    register struct table_elt *elt = sets[i].src_elt;
729818334Speter
729918334Speter	    while (elt && elt->prev_same_value)
730018334Speter	      elt = elt->prev_same_value;
730118334Speter
730218334Speter	    while (elt && elt->first_same_value == 0)
730318334Speter	      elt = elt->next_same_value;
730418334Speter	    sets[i].src_elt = elt ? elt->first_same_value : 0;
730518334Speter	  }
730618334Speter      }
730718334Speter
730818334Speter  /* Now insert the destinations into their equivalence classes.  */
730918334Speter
731018334Speter  for (i = 0; i < n_sets; i++)
731118334Speter    if (sets[i].rtl)
731218334Speter      {
731318334Speter	register rtx dest = SET_DEST (sets[i].rtl);
731418334Speter	register struct table_elt *elt;
731518334Speter
731618334Speter	/* Don't record value if we are not supposed to risk allocating
731718334Speter	   floating-point values in registers that might be wider than
731818334Speter	   memory.  */
731918334Speter	if ((flag_float_store
732018334Speter	     && GET_CODE (dest) == MEM
732118334Speter	     && FLOAT_MODE_P (GET_MODE (dest)))
732218334Speter	    /* Don't record values of destinations set inside a libcall block
732318334Speter	       since we might delete the libcall.  Things should have been set
732418334Speter	       up so we won't want to reuse such a value, but we play it safe
732518334Speter	       here.  */
732618334Speter	    || in_libcall_block
732718334Speter	    /* If we didn't put a REG_EQUAL value or a source into the hash
732818334Speter	       table, there is no point is recording DEST.  */
732918334Speter	    || sets[i].src_elt == 0
733018334Speter	    /* If DEST is a paradoxical SUBREG and SRC is a ZERO_EXTEND
733118334Speter	       or SIGN_EXTEND, don't record DEST since it can cause
733218334Speter	       some tracking to be wrong.
733318334Speter
733418334Speter	       ??? Think about this more later.  */
733518334Speter	    || (GET_CODE (dest) == SUBREG
733618334Speter		&& (GET_MODE_SIZE (GET_MODE (dest))
733718334Speter		    > GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
733818334Speter		&& (GET_CODE (sets[i].src) == SIGN_EXTEND
733918334Speter		    || GET_CODE (sets[i].src) == ZERO_EXTEND)))
734018334Speter	  continue;
734118334Speter
734218334Speter	/* STRICT_LOW_PART isn't part of the value BEING set,
734318334Speter	   and neither is the SUBREG inside it.
734418334Speter	   Note that in this case SETS[I].SRC_ELT is really SRC_EQV_ELT.  */
734518334Speter	if (GET_CODE (dest) == STRICT_LOW_PART)
734618334Speter	  dest = SUBREG_REG (XEXP (dest, 0));
734718334Speter
734818334Speter	if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG)
734918334Speter	  /* Registers must also be inserted into chains for quantities.  */
735018334Speter	  if (insert_regs (dest, sets[i].src_elt, 1))
735118334Speter	    {
735218334Speter	      /* If `insert_regs' changes something, the hash code must be
735318334Speter		 recalculated.  */
735418334Speter	      rehash_using_reg (dest);
735518334Speter	      sets[i].dest_hash = HASH (dest, GET_MODE (dest));
735618334Speter	    }
735718334Speter
735818334Speter	elt = insert (dest, sets[i].src_elt,
735918334Speter		      sets[i].dest_hash, GET_MODE (dest));
736018334Speter	elt->in_memory = (GET_CODE (sets[i].inner_dest) == MEM
736118334Speter			  && ! RTX_UNCHANGING_P (sets[i].inner_dest));
736218334Speter
736318334Speter	if (elt->in_memory)
736418334Speter	  {
736518334Speter	    /* This implicitly assumes a whole struct
736618334Speter	       need not have MEM_IN_STRUCT_P.
736718334Speter	       But a whole struct is *supposed* to have MEM_IN_STRUCT_P.  */
736818334Speter	    elt->in_struct = (MEM_IN_STRUCT_P (sets[i].inner_dest)
736918334Speter			      || sets[i].inner_dest != SET_DEST (sets[i].rtl));
737018334Speter	  }
737118334Speter
737218334Speter	/* If we have (set (subreg:m1 (reg:m2 foo) 0) (bar:m1)), M1 is no
737318334Speter	   narrower than M2, and both M1 and M2 are the same number of words,
737418334Speter	   we are also doing (set (reg:m2 foo) (subreg:m2 (bar:m1) 0)) so
737518334Speter	   make that equivalence as well.
737618334Speter
737718334Speter	   However, BAR may have equivalences for which gen_lowpart_if_possible
737818334Speter	   will produce a simpler value than gen_lowpart_if_possible applied to
737918334Speter	   BAR (e.g., if BAR was ZERO_EXTENDed from M2), so we will scan all
738018334Speter	   BAR's equivalences.  If we don't get a simplified form, make
738118334Speter	   the SUBREG.  It will not be used in an equivalence, but will
738218334Speter	   cause two similar assignments to be detected.
738318334Speter
738418334Speter	   Note the loop below will find SUBREG_REG (DEST) since we have
738518334Speter	   already entered SRC and DEST of the SET in the table.  */
738618334Speter
738718334Speter	if (GET_CODE (dest) == SUBREG
738818334Speter	    && (((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))) - 1)
738918334Speter		 / UNITS_PER_WORD)
739018334Speter		== (GET_MODE_SIZE (GET_MODE (dest)) - 1)/ UNITS_PER_WORD)
739118334Speter	    && (GET_MODE_SIZE (GET_MODE (dest))
739218334Speter		>= GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))
739318334Speter	    && sets[i].src_elt != 0)
739418334Speter	  {
739518334Speter	    enum machine_mode new_mode = GET_MODE (SUBREG_REG (dest));
739618334Speter	    struct table_elt *elt, *classp = 0;
739718334Speter
739818334Speter	    for (elt = sets[i].src_elt->first_same_value; elt;
739918334Speter		 elt = elt->next_same_value)
740018334Speter	      {
740118334Speter		rtx new_src = 0;
740218334Speter		unsigned src_hash;
740318334Speter		struct table_elt *src_elt;
740418334Speter
740518334Speter		/* Ignore invalid entries.  */
740618334Speter		if (GET_CODE (elt->exp) != REG
740718334Speter		    && ! exp_equiv_p (elt->exp, elt->exp, 1, 0))
740818334Speter		  continue;
740918334Speter
741018334Speter		new_src = gen_lowpart_if_possible (new_mode, elt->exp);
741118334Speter		if (new_src == 0)
741218334Speter		  new_src = gen_rtx (SUBREG, new_mode, elt->exp, 0);
741318334Speter
741418334Speter		src_hash = HASH (new_src, new_mode);
741518334Speter		src_elt = lookup (new_src, src_hash, new_mode);
741618334Speter
741718334Speter		/* Put the new source in the hash table is if isn't
741818334Speter		   already.  */
741918334Speter		if (src_elt == 0)
742018334Speter		  {
742118334Speter		    if (insert_regs (new_src, classp, 0))
742218334Speter		      {
742318334Speter			rehash_using_reg (new_src);
742418334Speter			src_hash = HASH (new_src, new_mode);
742518334Speter		      }
742618334Speter		    src_elt = insert (new_src, classp, src_hash, new_mode);
742718334Speter		    src_elt->in_memory = elt->in_memory;
742818334Speter		    src_elt->in_struct = elt->in_struct;
742918334Speter		  }
743018334Speter		else if (classp && classp != src_elt->first_same_value)
743118334Speter		  /* Show that two things that we've seen before are
743218334Speter		     actually the same.  */
743318334Speter		  merge_equiv_classes (src_elt, classp);
743418334Speter
743518334Speter		classp = src_elt->first_same_value;
743618334Speter	      }
743718334Speter	  }
743818334Speter      }
743918334Speter
744018334Speter  /* Special handling for (set REG0 REG1)
744118334Speter     where REG0 is the "cheapest", cheaper than REG1.
744218334Speter     After cse, REG1 will probably not be used in the sequel,
744318334Speter     so (if easily done) change this insn to (set REG1 REG0) and
744418334Speter     replace REG1 with REG0 in the previous insn that computed their value.
744518334Speter     Then REG1 will become a dead store and won't cloud the situation
744618334Speter     for later optimizations.
744718334Speter
744818334Speter     Do not make this change if REG1 is a hard register, because it will
744918334Speter     then be used in the sequel and we may be changing a two-operand insn
745018334Speter     into a three-operand insn.
745118334Speter
745218334Speter     Also do not do this if we are operating on a copy of INSN.  */
745318334Speter
745418334Speter  if (n_sets == 1 && sets[0].rtl && GET_CODE (SET_DEST (sets[0].rtl)) == REG
745518334Speter      && NEXT_INSN (PREV_INSN (insn)) == insn
745618334Speter      && GET_CODE (SET_SRC (sets[0].rtl)) == REG
745718334Speter      && REGNO (SET_SRC (sets[0].rtl)) >= FIRST_PSEUDO_REGISTER
745818334Speter      && REGNO_QTY_VALID_P (REGNO (SET_SRC (sets[0].rtl)))
745918334Speter      && (qty_first_reg[reg_qty[REGNO (SET_SRC (sets[0].rtl))]]
746018334Speter	  == REGNO (SET_DEST (sets[0].rtl))))
746118334Speter    {
746218334Speter      rtx prev = PREV_INSN (insn);
746318334Speter      while (prev && GET_CODE (prev) == NOTE)
746418334Speter	prev = PREV_INSN (prev);
746518334Speter
746618334Speter      if (prev && GET_CODE (prev) == INSN && GET_CODE (PATTERN (prev)) == SET
746718334Speter	  && SET_DEST (PATTERN (prev)) == SET_SRC (sets[0].rtl))
746818334Speter	{
746918334Speter	  rtx dest = SET_DEST (sets[0].rtl);
747018334Speter	  rtx note = find_reg_note (prev, REG_EQUIV, NULL_RTX);
747118334Speter
747218334Speter	  validate_change (prev, & SET_DEST (PATTERN (prev)), dest, 1);
747318334Speter	  validate_change (insn, & SET_DEST (sets[0].rtl),
747418334Speter			   SET_SRC (sets[0].rtl), 1);
747518334Speter	  validate_change (insn, & SET_SRC (sets[0].rtl), dest, 1);
747618334Speter	  apply_change_group ();
747718334Speter
747818334Speter	  /* If REG1 was equivalent to a constant, REG0 is not.  */
747918334Speter	  if (note)
748018334Speter	    PUT_REG_NOTE_KIND (note, REG_EQUAL);
748118334Speter
748218334Speter	  /* If there was a REG_WAS_0 note on PREV, remove it.  Move
748318334Speter	     any REG_WAS_0 note on INSN to PREV.  */
748418334Speter	  note = find_reg_note (prev, REG_WAS_0, NULL_RTX);
748518334Speter	  if (note)
748618334Speter	    remove_note (prev, note);
748718334Speter
748818334Speter	  note = find_reg_note (insn, REG_WAS_0, NULL_RTX);
748918334Speter	  if (note)
749018334Speter	    {
749118334Speter	      remove_note (insn, note);
749218334Speter	      XEXP (note, 1) = REG_NOTES (prev);
749318334Speter	      REG_NOTES (prev) = note;
749418334Speter	    }
749518334Speter
749618334Speter	  /* If INSN has a REG_EQUAL note, and this note mentions REG0,
749718334Speter	     then we must delete it, because the value in REG0 has changed.  */
749818334Speter	  note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
749918334Speter	  if (note && reg_mentioned_p (dest, XEXP (note, 0)))
750018334Speter	    remove_note (insn, note);
750118334Speter	}
750218334Speter    }
750318334Speter
750418334Speter  /* If this is a conditional jump insn, record any known equivalences due to
750518334Speter     the condition being tested.  */
750618334Speter
750718334Speter  last_jump_equiv_class = 0;
750818334Speter  if (GET_CODE (insn) == JUMP_INSN
750918334Speter      && n_sets == 1 && GET_CODE (x) == SET
751018334Speter      && GET_CODE (SET_SRC (x)) == IF_THEN_ELSE)
751118334Speter    record_jump_equiv (insn, 0);
751218334Speter
751318334Speter#ifdef HAVE_cc0
751418334Speter  /* If the previous insn set CC0 and this insn no longer references CC0,
751518334Speter     delete the previous insn.  Here we use the fact that nothing expects CC0
751618334Speter     to be valid over an insn, which is true until the final pass.  */
751718334Speter  if (prev_insn && GET_CODE (prev_insn) == INSN
751818334Speter      && (tem = single_set (prev_insn)) != 0
751918334Speter      && SET_DEST (tem) == cc0_rtx
752018334Speter      && ! reg_mentioned_p (cc0_rtx, x))
752118334Speter    {
752218334Speter      PUT_CODE (prev_insn, NOTE);
752318334Speter      NOTE_LINE_NUMBER (prev_insn) = NOTE_INSN_DELETED;
752418334Speter      NOTE_SOURCE_FILE (prev_insn) = 0;
752518334Speter    }
752618334Speter
752718334Speter  prev_insn_cc0 = this_insn_cc0;
752818334Speter  prev_insn_cc0_mode = this_insn_cc0_mode;
752918334Speter#endif
753018334Speter
753118334Speter  prev_insn = insn;
753218334Speter}
753318334Speter
753418334Speter/* Store 1 in *WRITES_PTR for those categories of memory ref
753518334Speter   that must be invalidated when the expression WRITTEN is stored in.
753618334Speter   If WRITTEN is null, say everything must be invalidated.  */
753718334Speter
753818334Speterstatic void
753918334Speternote_mem_written (written, writes_ptr)
754018334Speter     rtx written;
754118334Speter     struct write_data *writes_ptr;
754218334Speter{
754318334Speter  static struct write_data everything = {0, 1, 1, 1};
754418334Speter
754518334Speter  if (written == 0)
754618334Speter    *writes_ptr = everything;
754718334Speter  else if (GET_CODE (written) == MEM)
754818334Speter    {
754918334Speter      /* Pushing or popping the stack invalidates just the stack pointer. */
755018334Speter      rtx addr = XEXP (written, 0);
755118334Speter      if ((GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
755218334Speter	   || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
755318334Speter	  && GET_CODE (XEXP (addr, 0)) == REG
755418334Speter	  && REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
755518334Speter	{
755618334Speter	  writes_ptr->sp = 1;
755718334Speter	  return;
755818334Speter	}
755918334Speter      else if (GET_MODE (written) == BLKmode)
756018334Speter	*writes_ptr = everything;
756118334Speter      /* (mem (scratch)) means clobber everything.  */
756218334Speter      else if (GET_CODE (addr) == SCRATCH)
756318334Speter	*writes_ptr = everything;
756418334Speter      else if (cse_rtx_addr_varies_p (written))
756518334Speter	{
756618334Speter	  /* A varying address that is a sum indicates an array element,
756718334Speter	     and that's just as good as a structure element
756818334Speter	     in implying that we need not invalidate scalar variables.
756918334Speter	     However, we must allow QImode aliasing of scalars, because the
757018334Speter	     ANSI C standard allows character pointers to alias anything.  */
757118334Speter	  if (! ((MEM_IN_STRUCT_P (written)
757218334Speter		  || GET_CODE (XEXP (written, 0)) == PLUS)
757318334Speter		 && GET_MODE (written) != QImode))
757418334Speter	    writes_ptr->all = 1;
757518334Speter	  writes_ptr->nonscalar = 1;
757618334Speter	}
757718334Speter      writes_ptr->var = 1;
757818334Speter    }
757918334Speter}
758018334Speter
758118334Speter/* Perform invalidation on the basis of everything about an insn
758218334Speter   except for invalidating the actual places that are SET in it.
758318334Speter   This includes the places CLOBBERed, and anything that might
758418334Speter   alias with something that is SET or CLOBBERed.
758518334Speter
758618334Speter   W points to the writes_memory for this insn, a struct write_data
758718334Speter   saying which kinds of memory references must be invalidated.
758818334Speter   X is the pattern of the insn.  */
758918334Speter
759018334Speterstatic void
759118334Speterinvalidate_from_clobbers (w, x)
759218334Speter     struct write_data *w;
759318334Speter     rtx x;
759418334Speter{
759518334Speter  /* If W->var is not set, W specifies no action.
759618334Speter     If W->all is set, this step gets all memory refs
759718334Speter     so they can be ignored in the rest of this function.  */
759818334Speter  if (w->var)
759918334Speter    invalidate_memory (w);
760018334Speter
760118334Speter  if (w->sp)
760218334Speter    {
760318334Speter      if (reg_tick[STACK_POINTER_REGNUM] >= 0)
760418334Speter	reg_tick[STACK_POINTER_REGNUM]++;
760518334Speter
760618334Speter      /* This should be *very* rare.  */
760718334Speter      if (TEST_HARD_REG_BIT (hard_regs_in_table, STACK_POINTER_REGNUM))
760818334Speter	invalidate (stack_pointer_rtx, VOIDmode);
760918334Speter    }
761018334Speter
761118334Speter  if (GET_CODE (x) == CLOBBER)
761218334Speter    {
761318334Speter      rtx ref = XEXP (x, 0);
761418334Speter      if (ref)
761518334Speter	{
761618334Speter	  if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
761718334Speter	      || (GET_CODE (ref) == MEM && ! w->all))
761818334Speter	    invalidate (ref, VOIDmode);
761918334Speter	  else if (GET_CODE (ref) == STRICT_LOW_PART
762018334Speter		   || GET_CODE (ref) == ZERO_EXTRACT)
762118334Speter	    invalidate (XEXP (ref, 0), GET_MODE (ref));
762218334Speter	}
762318334Speter    }
762418334Speter  else if (GET_CODE (x) == PARALLEL)
762518334Speter    {
762618334Speter      register int i;
762718334Speter      for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
762818334Speter	{
762918334Speter	  register rtx y = XVECEXP (x, 0, i);
763018334Speter	  if (GET_CODE (y) == CLOBBER)
763118334Speter	    {
763218334Speter	      rtx ref = XEXP (y, 0);
763318334Speter	      if (ref)
763418334Speter		{
763518334Speter		  if (GET_CODE (ref) == REG || GET_CODE (ref) == SUBREG
763618334Speter		      || (GET_CODE (ref) == MEM && !w->all))
763718334Speter		    invalidate (ref, VOIDmode);
763818334Speter		  else if (GET_CODE (ref) == STRICT_LOW_PART
763918334Speter			   || GET_CODE (ref) == ZERO_EXTRACT)
764018334Speter		    invalidate (XEXP (ref, 0), GET_MODE (ref));
764118334Speter		}
764218334Speter	    }
764318334Speter	}
764418334Speter    }
764518334Speter}
764618334Speter
764718334Speter/* Process X, part of the REG_NOTES of an insn.  Look at any REG_EQUAL notes
764818334Speter   and replace any registers in them with either an equivalent constant
764918334Speter   or the canonical form of the register.  If we are inside an address,
765018334Speter   only do this if the address remains valid.
765118334Speter
765218334Speter   OBJECT is 0 except when within a MEM in which case it is the MEM.
765318334Speter
765418334Speter   Return the replacement for X.  */
765518334Speter
765618334Speterstatic rtx
765718334Spetercse_process_notes (x, object)
765818334Speter     rtx x;
765918334Speter     rtx object;
766018334Speter{
766118334Speter  enum rtx_code code = GET_CODE (x);
766218334Speter  char *fmt = GET_RTX_FORMAT (code);
766318334Speter  int i;
766418334Speter
766518334Speter  switch (code)
766618334Speter    {
766718334Speter    case CONST_INT:
766818334Speter    case CONST:
766918334Speter    case SYMBOL_REF:
767018334Speter    case LABEL_REF:
767118334Speter    case CONST_DOUBLE:
767218334Speter    case PC:
767318334Speter    case CC0:
767418334Speter    case LO_SUM:
767518334Speter      return x;
767618334Speter
767718334Speter    case MEM:
767818334Speter      XEXP (x, 0) = cse_process_notes (XEXP (x, 0), x);
767918334Speter      return x;
768018334Speter
768118334Speter    case EXPR_LIST:
768218334Speter    case INSN_LIST:
768318334Speter      if (REG_NOTE_KIND (x) == REG_EQUAL)
768418334Speter	XEXP (x, 0) = cse_process_notes (XEXP (x, 0), NULL_RTX);
768518334Speter      if (XEXP (x, 1))
768618334Speter	XEXP (x, 1) = cse_process_notes (XEXP (x, 1), NULL_RTX);
768718334Speter      return x;
768818334Speter
768918334Speter    case SIGN_EXTEND:
769018334Speter    case ZERO_EXTEND:
769118334Speter      {
769218334Speter	rtx new = cse_process_notes (XEXP (x, 0), object);
769318334Speter	/* We don't substitute VOIDmode constants into these rtx,
769418334Speter	   since they would impede folding.  */
769518334Speter	if (GET_MODE (new) != VOIDmode)
769618334Speter	  validate_change (object, &XEXP (x, 0), new, 0);
769718334Speter	return x;
769818334Speter      }
769918334Speter
770018334Speter    case REG:
770118334Speter      i = reg_qty[REGNO (x)];
770218334Speter
770318334Speter      /* Return a constant or a constant register.  */
770418334Speter      if (REGNO_QTY_VALID_P (REGNO (x))
770518334Speter	  && qty_const[i] != 0
770618334Speter	  && (CONSTANT_P (qty_const[i])
770718334Speter	      || GET_CODE (qty_const[i]) == REG))
770818334Speter	{
770918334Speter	  rtx new = gen_lowpart_if_possible (GET_MODE (x), qty_const[i]);
771018334Speter	  if (new)
771118334Speter	    return new;
771218334Speter	}
771318334Speter
771418334Speter      /* Otherwise, canonicalize this register.  */
771518334Speter      return canon_reg (x, NULL_RTX);
771618334Speter    }
771718334Speter
771818334Speter  for (i = 0; i < GET_RTX_LENGTH (code); i++)
771918334Speter    if (fmt[i] == 'e')
772018334Speter      validate_change (object, &XEXP (x, i),
772118334Speter		       cse_process_notes (XEXP (x, i), object), 0);
772218334Speter
772318334Speter  return x;
772418334Speter}
772518334Speter
772618334Speter/* Find common subexpressions between the end test of a loop and the beginning
772718334Speter   of the loop.  LOOP_START is the CODE_LABEL at the start of a loop.
772818334Speter
772918334Speter   Often we have a loop where an expression in the exit test is used
773018334Speter   in the body of the loop.  For example "while (*p) *q++ = *p++;".
773118334Speter   Because of the way we duplicate the loop exit test in front of the loop,
773218334Speter   however, we don't detect that common subexpression.  This will be caught
773318334Speter   when global cse is implemented, but this is a quite common case.
773418334Speter
773518334Speter   This function handles the most common cases of these common expressions.
773618334Speter   It is called after we have processed the basic block ending with the
773718334Speter   NOTE_INSN_LOOP_END note that ends a loop and the previous JUMP_INSN
773818334Speter   jumps to a label used only once.  */
773918334Speter
774018334Speterstatic void
774118334Spetercse_around_loop (loop_start)
774218334Speter     rtx loop_start;
774318334Speter{
774418334Speter  rtx insn;
774518334Speter  int i;
774618334Speter  struct table_elt *p;
774718334Speter
774818334Speter  /* If the jump at the end of the loop doesn't go to the start, we don't
774918334Speter     do anything.  */
775018334Speter  for (insn = PREV_INSN (loop_start);
775118334Speter       insn && (GET_CODE (insn) == NOTE && NOTE_LINE_NUMBER (insn) >= 0);
775218334Speter       insn = PREV_INSN (insn))
775318334Speter    ;
775418334Speter
775518334Speter  if (insn == 0
775618334Speter      || GET_CODE (insn) != NOTE
775718334Speter      || NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG)
775818334Speter    return;
775918334Speter
776018334Speter  /* If the last insn of the loop (the end test) was an NE comparison,
776118334Speter     we will interpret it as an EQ comparison, since we fell through
776218334Speter     the loop.  Any equivalences resulting from that comparison are
776318334Speter     therefore not valid and must be invalidated.  */
776418334Speter  if (last_jump_equiv_class)
776518334Speter    for (p = last_jump_equiv_class->first_same_value; p;
776618334Speter	 p = p->next_same_value)
776718334Speter      if (GET_CODE (p->exp) == MEM || GET_CODE (p->exp) == REG
776818334Speter	  || (GET_CODE (p->exp) == SUBREG
776918334Speter	      && GET_CODE (SUBREG_REG (p->exp)) == REG))
777018334Speter	invalidate (p->exp, VOIDmode);
777118334Speter      else if (GET_CODE (p->exp) == STRICT_LOW_PART
777218334Speter	       || GET_CODE (p->exp) == ZERO_EXTRACT)
777318334Speter	invalidate (XEXP (p->exp, 0), GET_MODE (p->exp));
777418334Speter
777518334Speter  /* Process insns starting after LOOP_START until we hit a CALL_INSN or
777618334Speter     a CODE_LABEL (we could handle a CALL_INSN, but it isn't worth it).
777718334Speter
777818334Speter     The only thing we do with SET_DEST is invalidate entries, so we
777918334Speter     can safely process each SET in order.  It is slightly less efficient
778018334Speter     to do so, but we only want to handle the most common cases.  */
778118334Speter
778218334Speter  for (insn = NEXT_INSN (loop_start);
778318334Speter       GET_CODE (insn) != CALL_INSN && GET_CODE (insn) != CODE_LABEL
778418334Speter       && ! (GET_CODE (insn) == NOTE
778518334Speter	     && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END);
778618334Speter       insn = NEXT_INSN (insn))
778718334Speter    {
778818334Speter      if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
778918334Speter	  && (GET_CODE (PATTERN (insn)) == SET
779018334Speter	      || GET_CODE (PATTERN (insn)) == CLOBBER))
779118334Speter	cse_set_around_loop (PATTERN (insn), insn, loop_start);
779218334Speter      else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
779318334Speter	       && GET_CODE (PATTERN (insn)) == PARALLEL)
779418334Speter	for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
779518334Speter	  if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET
779618334Speter	      || GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == CLOBBER)
779718334Speter	    cse_set_around_loop (XVECEXP (PATTERN (insn), 0, i), insn,
779818334Speter				 loop_start);
779918334Speter    }
780018334Speter}
780118334Speter
780218334Speter/* Variable used for communications between the next two routines.  */
780318334Speter
780418334Speterstatic struct write_data skipped_writes_memory;
780518334Speter
780618334Speter/* Process one SET of an insn that was skipped.  We ignore CLOBBERs
780718334Speter   since they are done elsewhere.  This function is called via note_stores.  */
780818334Speter
780918334Speterstatic void
781018334Speterinvalidate_skipped_set (dest, set)
781118334Speter     rtx set;
781218334Speter     rtx dest;
781318334Speter{
781418334Speter  if (GET_CODE (dest) == MEM)
781518334Speter    note_mem_written (dest, &skipped_writes_memory);
781618334Speter
781718334Speter  /* There are times when an address can appear varying and be a PLUS
781818334Speter     during this scan when it would be a fixed address were we to know
781918334Speter     the proper equivalences.  So promote "nonscalar" to be "all".  */
782018334Speter  if (skipped_writes_memory.nonscalar)
782118334Speter    skipped_writes_memory.all = 1;
782218334Speter
782348743Sobrien  if (GET_CODE (set) == CLOBBER
782448743Sobrien#ifdef HAVE_cc0
782548743Sobrien      || dest == cc0_rtx
782648743Sobrien#endif
782748743Sobrien      || dest == pc_rtx)
782848743Sobrien    return;
782948743Sobrien
783018334Speter  if (GET_CODE (dest) == REG || GET_CODE (dest) == SUBREG
783118334Speter      || (! skipped_writes_memory.all && ! cse_rtx_addr_varies_p (dest)))
783218334Speter    invalidate (dest, VOIDmode);
783318334Speter  else if (GET_CODE (dest) == STRICT_LOW_PART
783418334Speter	   || GET_CODE (dest) == ZERO_EXTRACT)
783518334Speter    invalidate (XEXP (dest, 0), GET_MODE (dest));
783618334Speter}
783718334Speter
783818334Speter/* Invalidate all insns from START up to the end of the function or the
783918334Speter   next label.  This called when we wish to CSE around a block that is
784018334Speter   conditionally executed.  */
784118334Speter
784218334Speterstatic void
784318334Speterinvalidate_skipped_block (start)
784418334Speter     rtx start;
784518334Speter{
784618334Speter  rtx insn;
784718334Speter  static struct write_data init = {0, 0, 0, 0};
784818334Speter  static struct write_data everything = {0, 1, 1, 1};
784918334Speter
785018334Speter  for (insn = start; insn && GET_CODE (insn) != CODE_LABEL;
785118334Speter       insn = NEXT_INSN (insn))
785218334Speter    {
785318334Speter      if (GET_RTX_CLASS (GET_CODE (insn)) != 'i')
785418334Speter	continue;
785518334Speter
785618334Speter      skipped_writes_memory = init;
785718334Speter
785818334Speter      if (GET_CODE (insn) == CALL_INSN)
785918334Speter	{
786018334Speter	  invalidate_for_call ();
786118334Speter	  skipped_writes_memory = everything;
786218334Speter	}
786318334Speter
786418334Speter      note_stores (PATTERN (insn), invalidate_skipped_set);
786518334Speter      invalidate_from_clobbers (&skipped_writes_memory, PATTERN (insn));
786618334Speter    }
786718334Speter}
786818334Speter
786918334Speter/* Used for communication between the following two routines; contains a
787018334Speter   value to be checked for modification.  */
787118334Speter
787218334Speterstatic rtx cse_check_loop_start_value;
787318334Speter
787418334Speter/* If modifying X will modify the value in CSE_CHECK_LOOP_START_VALUE,
787518334Speter   indicate that fact by setting CSE_CHECK_LOOP_START_VALUE to 0.  */
787618334Speter
787718334Speterstatic void
787818334Spetercse_check_loop_start (x, set)
787918334Speter     rtx x;
788018334Speter     rtx set;
788118334Speter{
788218334Speter  if (cse_check_loop_start_value == 0
788318334Speter      || GET_CODE (x) == CC0 || GET_CODE (x) == PC)
788418334Speter    return;
788518334Speter
788618334Speter  if ((GET_CODE (x) == MEM && GET_CODE (cse_check_loop_start_value) == MEM)
788718334Speter      || reg_overlap_mentioned_p (x, cse_check_loop_start_value))
788818334Speter    cse_check_loop_start_value = 0;
788918334Speter}
789018334Speter
789118334Speter/* X is a SET or CLOBBER contained in INSN that was found near the start of
789218334Speter   a loop that starts with the label at LOOP_START.
789318334Speter
789418334Speter   If X is a SET, we see if its SET_SRC is currently in our hash table.
789518334Speter   If so, we see if it has a value equal to some register used only in the
789618334Speter   loop exit code (as marked by jump.c).
789718334Speter
789818334Speter   If those two conditions are true, we search backwards from the start of
789918334Speter   the loop to see if that same value was loaded into a register that still
790018334Speter   retains its value at the start of the loop.
790118334Speter
790218334Speter   If so, we insert an insn after the load to copy the destination of that
790318334Speter   load into the equivalent register and (try to) replace our SET_SRC with that
790418334Speter   register.
790518334Speter
790618334Speter   In any event, we invalidate whatever this SET or CLOBBER modifies.  */
790718334Speter
790818334Speterstatic void
790918334Spetercse_set_around_loop (x, insn, loop_start)
791018334Speter     rtx x;
791118334Speter     rtx insn;
791218334Speter     rtx loop_start;
791318334Speter{
791418334Speter  struct table_elt *src_elt;
791518334Speter  static struct write_data init = {0, 0, 0, 0};
791618334Speter  struct write_data writes_memory;
791718334Speter
791818334Speter  writes_memory = init;
791918334Speter
792018334Speter  /* If this is a SET, see if we can replace SET_SRC, but ignore SETs that
792118334Speter     are setting PC or CC0 or whose SET_SRC is already a register.  */
792218334Speter  if (GET_CODE (x) == SET
792318334Speter      && GET_CODE (SET_DEST (x)) != PC && GET_CODE (SET_DEST (x)) != CC0
792418334Speter      && GET_CODE (SET_SRC (x)) != REG)
792518334Speter    {
792618334Speter      src_elt = lookup (SET_SRC (x),
792718334Speter			HASH (SET_SRC (x), GET_MODE (SET_DEST (x))),
792818334Speter			GET_MODE (SET_DEST (x)));
792918334Speter
793018334Speter      if (src_elt)
793118334Speter	for (src_elt = src_elt->first_same_value; src_elt;
793218334Speter	     src_elt = src_elt->next_same_value)
793318334Speter	  if (GET_CODE (src_elt->exp) == REG && REG_LOOP_TEST_P (src_elt->exp)
793418334Speter	      && COST (src_elt->exp) < COST (SET_SRC (x)))
793518334Speter	    {
793618334Speter	      rtx p, set;
793718334Speter
793818334Speter	      /* Look for an insn in front of LOOP_START that sets
793918334Speter		 something in the desired mode to SET_SRC (x) before we hit
794018334Speter		 a label or CALL_INSN.  */
794118334Speter
794218334Speter	      for (p = prev_nonnote_insn (loop_start);
794318334Speter		   p && GET_CODE (p) != CALL_INSN
794418334Speter		   && GET_CODE (p) != CODE_LABEL;
794518334Speter		   p = prev_nonnote_insn  (p))
794618334Speter		if ((set = single_set (p)) != 0
794718334Speter		    && GET_CODE (SET_DEST (set)) == REG
794818334Speter		    && GET_MODE (SET_DEST (set)) == src_elt->mode
794918334Speter		    && rtx_equal_p (SET_SRC (set), SET_SRC (x)))
795018334Speter		  {
795118334Speter		    /* We now have to ensure that nothing between P
795218334Speter		       and LOOP_START modified anything referenced in
795318334Speter		       SET_SRC (x).  We know that nothing within the loop
795418334Speter		       can modify it, or we would have invalidated it in
795518334Speter		       the hash table.  */
795618334Speter		    rtx q;
795718334Speter
795818334Speter		    cse_check_loop_start_value = SET_SRC (x);
795918334Speter		    for (q = p; q != loop_start; q = NEXT_INSN (q))
796018334Speter		      if (GET_RTX_CLASS (GET_CODE (q)) == 'i')
796118334Speter			note_stores (PATTERN (q), cse_check_loop_start);
796218334Speter
796318334Speter		    /* If nothing was changed and we can replace our
796418334Speter		       SET_SRC, add an insn after P to copy its destination
796518334Speter		       to what we will be replacing SET_SRC with.  */
796618334Speter		    if (cse_check_loop_start_value
796718334Speter			&& validate_change (insn, &SET_SRC (x),
796818334Speter					    src_elt->exp, 0))
796918334Speter		      emit_insn_after (gen_move_insn (src_elt->exp,
797018334Speter						      SET_DEST (set)),
797118334Speter				       p);
797218334Speter		    break;
797318334Speter		  }
797418334Speter	    }
797518334Speter    }
797618334Speter
797718334Speter  /* Now invalidate anything modified by X.  */
797818334Speter  note_mem_written (SET_DEST (x), &writes_memory);
797918334Speter
798018334Speter  if (writes_memory.var)
798118334Speter    invalidate_memory (&writes_memory);
798218334Speter
798318334Speter  /* See comment on similar code in cse_insn for explanation of these tests. */
798418334Speter  if (GET_CODE (SET_DEST (x)) == REG || GET_CODE (SET_DEST (x)) == SUBREG
798518334Speter      || (GET_CODE (SET_DEST (x)) == MEM && ! writes_memory.all
798618334Speter	  && ! cse_rtx_addr_varies_p (SET_DEST (x))))
798718334Speter    invalidate (SET_DEST (x), VOIDmode);
798818334Speter  else if (GET_CODE (SET_DEST (x)) == STRICT_LOW_PART
798918334Speter	   || GET_CODE (SET_DEST (x)) == ZERO_EXTRACT)
799018334Speter    invalidate (XEXP (SET_DEST (x), 0), GET_MODE (SET_DEST (x)));
799118334Speter}
799218334Speter
799318334Speter/* Find the end of INSN's basic block and return its range,
799418334Speter   the total number of SETs in all the insns of the block, the last insn of the
799518334Speter   block, and the branch path.
799618334Speter
799718334Speter   The branch path indicates which branches should be followed.  If a non-zero
799818334Speter   path size is specified, the block should be rescanned and a different set
799918334Speter   of branches will be taken.  The branch path is only used if
800018334Speter   FLAG_CSE_FOLLOW_JUMPS or FLAG_CSE_SKIP_BLOCKS is non-zero.
800118334Speter
800218334Speter   DATA is a pointer to a struct cse_basic_block_data, defined below, that is
800318334Speter   used to describe the block.  It is filled in with the information about
800418334Speter   the current block.  The incoming structure's branch path, if any, is used
800518334Speter   to construct the output branch path.  */
800618334Speter
800718334Spetervoid
800818334Spetercse_end_of_basic_block (insn, data, follow_jumps, after_loop, skip_blocks)
800918334Speter     rtx insn;
801018334Speter     struct cse_basic_block_data *data;
801118334Speter     int follow_jumps;
801218334Speter     int after_loop;
801318334Speter     int skip_blocks;
801418334Speter{
801518334Speter  rtx p = insn, q;
801618334Speter  int nsets = 0;
801718334Speter  int low_cuid = INSN_CUID (insn), high_cuid = INSN_CUID (insn);
801818334Speter  rtx next = GET_RTX_CLASS (GET_CODE (insn)) == 'i' ? insn : next_real_insn (insn);
801918334Speter  int path_size = data->path_size;
802018334Speter  int path_entry = 0;
802118334Speter  int i;
802218334Speter
802318334Speter  /* Update the previous branch path, if any.  If the last branch was
802418334Speter     previously TAKEN, mark it NOT_TAKEN.  If it was previously NOT_TAKEN,
802518334Speter     shorten the path by one and look at the previous branch.  We know that
802618334Speter     at least one branch must have been taken if PATH_SIZE is non-zero.  */
802718334Speter  while (path_size > 0)
802818334Speter    {
802918334Speter      if (data->path[path_size - 1].status != NOT_TAKEN)
803018334Speter	{
803118334Speter	  data->path[path_size - 1].status = NOT_TAKEN;
803218334Speter	  break;
803318334Speter	}
803418334Speter      else
803518334Speter	path_size--;
803618334Speter    }
803718334Speter
803818334Speter  /* Scan to end of this basic block.  */
803918334Speter  while (p && GET_CODE (p) != CODE_LABEL)
804018334Speter    {
804118334Speter      /* Don't cse out the end of a loop.  This makes a difference
804218334Speter	 only for the unusual loops that always execute at least once;
804318334Speter	 all other loops have labels there so we will stop in any case.
804418334Speter	 Cse'ing out the end of the loop is dangerous because it
804518334Speter	 might cause an invariant expression inside the loop
804618334Speter	 to be reused after the end of the loop.  This would make it
804718334Speter	 hard to move the expression out of the loop in loop.c,
804818334Speter	 especially if it is one of several equivalent expressions
804918334Speter	 and loop.c would like to eliminate it.
805018334Speter
805118334Speter	 If we are running after loop.c has finished, we can ignore
805218334Speter	 the NOTE_INSN_LOOP_END.  */
805318334Speter
805418334Speter      if (! after_loop && GET_CODE (p) == NOTE
805518334Speter	  && NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
805618334Speter	break;
805718334Speter
805818334Speter      /* Don't cse over a call to setjmp; on some machines (eg vax)
805918334Speter	 the regs restored by the longjmp come from
806018334Speter	 a later time than the setjmp.  */
806118334Speter      if (GET_CODE (p) == NOTE
806218334Speter	  && NOTE_LINE_NUMBER (p) == NOTE_INSN_SETJMP)
806318334Speter	break;
806418334Speter
806518334Speter      /* A PARALLEL can have lots of SETs in it,
806618334Speter	 especially if it is really an ASM_OPERANDS.  */
806718334Speter      if (GET_RTX_CLASS (GET_CODE (p)) == 'i'
806818334Speter	  && GET_CODE (PATTERN (p)) == PARALLEL)
806918334Speter	nsets += XVECLEN (PATTERN (p), 0);
807018334Speter      else if (GET_CODE (p) != NOTE)
807118334Speter	nsets += 1;
807218334Speter
807318334Speter      /* Ignore insns made by CSE; they cannot affect the boundaries of
807418334Speter	 the basic block.  */
807518334Speter
807618334Speter      if (INSN_UID (p) <= max_uid && INSN_CUID (p) > high_cuid)
807718334Speter	high_cuid = INSN_CUID (p);
807818334Speter      if (INSN_UID (p) <= max_uid && INSN_CUID (p) < low_cuid)
807918334Speter	low_cuid = INSN_CUID (p);
808018334Speter
808118334Speter      /* See if this insn is in our branch path.  If it is and we are to
808218334Speter	 take it, do so.  */
808318334Speter      if (path_entry < path_size && data->path[path_entry].branch == p)
808418334Speter	{
808518334Speter	  if (data->path[path_entry].status != NOT_TAKEN)
808618334Speter	    p = JUMP_LABEL (p);
808718334Speter
808818334Speter	  /* Point to next entry in path, if any.  */
808918334Speter	  path_entry++;
809018334Speter	}
809118334Speter
809218334Speter      /* If this is a conditional jump, we can follow it if -fcse-follow-jumps
809318334Speter	 was specified, we haven't reached our maximum path length, there are
809418334Speter	 insns following the target of the jump, this is the only use of the
809518334Speter	 jump label, and the target label is preceded by a BARRIER.
809618334Speter
809718334Speter	 Alternatively, we can follow the jump if it branches around a
809818334Speter	 block of code and there are no other branches into the block.
809918334Speter	 In this case invalidate_skipped_block will be called to invalidate any
810018334Speter	 registers set in the block when following the jump.  */
810118334Speter
810218334Speter      else if ((follow_jumps || skip_blocks) && path_size < PATHLENGTH - 1
810318334Speter	       && GET_CODE (p) == JUMP_INSN
810418334Speter      	       && GET_CODE (PATTERN (p)) == SET
810518334Speter	       && GET_CODE (SET_SRC (PATTERN (p))) == IF_THEN_ELSE
810618334Speter	       && LABEL_NUSES (JUMP_LABEL (p)) == 1
810718334Speter	       && NEXT_INSN (JUMP_LABEL (p)) != 0)
810818334Speter	{
810918334Speter	  for (q = PREV_INSN (JUMP_LABEL (p)); q; q = PREV_INSN (q))
811018334Speter	    if ((GET_CODE (q) != NOTE
811118334Speter	         || NOTE_LINE_NUMBER (q) == NOTE_INSN_LOOP_END
811218334Speter	         || NOTE_LINE_NUMBER (q) == NOTE_INSN_SETJMP)
811318334Speter	        && (GET_CODE (q) != CODE_LABEL || LABEL_NUSES (q) != 0))
811418334Speter	      break;
811518334Speter
811618334Speter	  /* If we ran into a BARRIER, this code is an extension of the
811718334Speter	     basic block when the branch is taken.  */
811818334Speter	  if (follow_jumps && q != 0 && GET_CODE (q) == BARRIER)
811918334Speter	    {
812018334Speter	      /* Don't allow ourself to keep walking around an
812118334Speter		 always-executed loop.  */
812218334Speter	      if (next_real_insn (q) == next)
812318334Speter		{
812418334Speter		  p = NEXT_INSN (p);
812518334Speter		  continue;
812618334Speter		}
812718334Speter
812818334Speter	      /* Similarly, don't put a branch in our path more than once.  */
812918334Speter	      for (i = 0; i < path_entry; i++)
813018334Speter		if (data->path[i].branch == p)
813118334Speter		  break;
813218334Speter
813318334Speter	      if (i != path_entry)
813418334Speter		break;
813518334Speter
813618334Speter	      data->path[path_entry].branch = p;
813718334Speter	      data->path[path_entry++].status = TAKEN;
813818334Speter
813918334Speter	      /* This branch now ends our path.  It was possible that we
814018334Speter		 didn't see this branch the last time around (when the
814118334Speter		 insn in front of the target was a JUMP_INSN that was
814218334Speter		 turned into a no-op).  */
814318334Speter	      path_size = path_entry;
814418334Speter
814518334Speter	      p = JUMP_LABEL (p);
814618334Speter	      /* Mark block so we won't scan it again later.  */
814718334Speter	      PUT_MODE (NEXT_INSN (p), QImode);
814818334Speter	    }
814918334Speter	  /* Detect a branch around a block of code.  */
815018334Speter	  else if (skip_blocks && q != 0 && GET_CODE (q) != CODE_LABEL)
815118334Speter	    {
815218334Speter	      register rtx tmp;
815318334Speter
815418334Speter	      if (next_real_insn (q) == next)
815518334Speter		{
815618334Speter		  p = NEXT_INSN (p);
815718334Speter		  continue;
815818334Speter		}
815918334Speter
816018334Speter	      for (i = 0; i < path_entry; i++)
816118334Speter		if (data->path[i].branch == p)
816218334Speter		  break;
816318334Speter
816418334Speter	      if (i != path_entry)
816518334Speter		break;
816618334Speter
816718334Speter	      /* This is no_labels_between_p (p, q) with an added check for
816818334Speter		 reaching the end of a function (in case Q precedes P).  */
816918334Speter	      for (tmp = NEXT_INSN (p); tmp && tmp != q; tmp = NEXT_INSN (tmp))
817018334Speter		if (GET_CODE (tmp) == CODE_LABEL)
817118334Speter		  break;
817218334Speter
817318334Speter	      if (tmp == q)
817418334Speter		{
817518334Speter		  data->path[path_entry].branch = p;
817618334Speter		  data->path[path_entry++].status = AROUND;
817718334Speter
817818334Speter		  path_size = path_entry;
817918334Speter
818018334Speter		  p = JUMP_LABEL (p);
818118334Speter		  /* Mark block so we won't scan it again later.  */
818218334Speter		  PUT_MODE (NEXT_INSN (p), QImode);
818318334Speter		}
818418334Speter	    }
818518334Speter	}
818618334Speter      p = NEXT_INSN (p);
818718334Speter    }
818818334Speter
818918334Speter  data->low_cuid = low_cuid;
819018334Speter  data->high_cuid = high_cuid;
819118334Speter  data->nsets = nsets;
819218334Speter  data->last = p;
819318334Speter
819418334Speter  /* If all jumps in the path are not taken, set our path length to zero
819518334Speter     so a rescan won't be done.  */
819618334Speter  for (i = path_size - 1; i >= 0; i--)
819718334Speter    if (data->path[i].status != NOT_TAKEN)
819818334Speter      break;
819918334Speter
820018334Speter  if (i == -1)
820118334Speter    data->path_size = 0;
820218334Speter  else
820318334Speter    data->path_size = path_size;
820418334Speter
820518334Speter  /* End the current branch path.  */
820618334Speter  data->path[path_size].branch = 0;
820718334Speter}
820818334Speter
820918334Speter/* Perform cse on the instructions of a function.
821018334Speter   F is the first instruction.
821118334Speter   NREGS is one plus the highest pseudo-reg number used in the instruction.
821218334Speter
821318334Speter   AFTER_LOOP is 1 if this is the cse call done after loop optimization
821418334Speter   (only if -frerun-cse-after-loop).
821518334Speter
821618334Speter   Returns 1 if jump_optimize should be redone due to simplifications
821718334Speter   in conditional jump instructions.  */
821818334Speter
821918334Speterint
822018334Spetercse_main (f, nregs, after_loop, file)
822118334Speter     rtx f;
822218334Speter     int nregs;
822318334Speter     int after_loop;
822418334Speter     FILE *file;
822518334Speter{
822618334Speter  struct cse_basic_block_data val;
822718334Speter  register rtx insn = f;
822818334Speter  register int i;
822918334Speter
823018334Speter  cse_jumps_altered = 0;
823118334Speter  recorded_label_ref = 0;
823218334Speter  constant_pool_entries_cost = 0;
823318334Speter  val.path_size = 0;
823418334Speter
823518334Speter  init_recog ();
823618334Speter
823718334Speter  max_reg = nregs;
823818334Speter
823918334Speter  all_minus_one = (int *) alloca (nregs * sizeof (int));
824018334Speter  consec_ints = (int *) alloca (nregs * sizeof (int));
824118334Speter
824218334Speter  for (i = 0; i < nregs; i++)
824318334Speter    {
824418334Speter      all_minus_one[i] = -1;
824518334Speter      consec_ints[i] = i;
824618334Speter    }
824718334Speter
824818334Speter  reg_next_eqv = (int *) alloca (nregs * sizeof (int));
824918334Speter  reg_prev_eqv = (int *) alloca (nregs * sizeof (int));
825018334Speter  reg_qty = (int *) alloca (nregs * sizeof (int));
825118334Speter  reg_in_table = (int *) alloca (nregs * sizeof (int));
825218334Speter  reg_tick = (int *) alloca (nregs * sizeof (int));
825318334Speter
825418334Speter#ifdef LOAD_EXTEND_OP
825518334Speter
825618334Speter  /* Allocate scratch rtl here.  cse_insn will fill in the memory reference
825718334Speter     and change the code and mode as appropriate.  */
825818334Speter  memory_extend_rtx = gen_rtx (ZERO_EXTEND, VOIDmode, 0);
825918334Speter#endif
826018334Speter
826118334Speter  /* Discard all the free elements of the previous function
826218334Speter     since they are allocated in the temporarily obstack.  */
826318334Speter  bzero ((char *) table, sizeof table);
826418334Speter  free_element_chain = 0;
826518334Speter  n_elements_made = 0;
826618334Speter
826718334Speter  /* Find the largest uid.  */
826818334Speter
826918334Speter  max_uid = get_max_uid ();
827018334Speter  uid_cuid = (int *) alloca ((max_uid + 1) * sizeof (int));
827118334Speter  bzero ((char *) uid_cuid, (max_uid + 1) * sizeof (int));
827218334Speter
827318334Speter  /* Compute the mapping from uids to cuids.
827418334Speter     CUIDs are numbers assigned to insns, like uids,
827518334Speter     except that cuids increase monotonically through the code.
827618334Speter     Don't assign cuids to line-number NOTEs, so that the distance in cuids
827718334Speter     between two insns is not affected by -g.  */
827818334Speter
827918334Speter  for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
828018334Speter    {
828118334Speter      if (GET_CODE (insn) != NOTE
828218334Speter	  || NOTE_LINE_NUMBER (insn) < 0)
828318334Speter	INSN_CUID (insn) = ++i;
828418334Speter      else
828518334Speter	/* Give a line number note the same cuid as preceding insn.  */
828618334Speter	INSN_CUID (insn) = i;
828718334Speter    }
828818334Speter
828918334Speter  /* Initialize which registers are clobbered by calls.  */
829018334Speter
829118334Speter  CLEAR_HARD_REG_SET (regs_invalidated_by_call);
829218334Speter
829318334Speter  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
829418334Speter    if ((call_used_regs[i]
829518334Speter	 /* Used to check !fixed_regs[i] here, but that isn't safe;
829618334Speter	    fixed regs are still call-clobbered, and sched can get
829718334Speter	    confused if they can "live across calls".
829818334Speter
829918334Speter	    The frame pointer is always preserved across calls.  The arg
830018334Speter	    pointer is if it is fixed.  The stack pointer usually is, unless
830118334Speter	    RETURN_POPS_ARGS, in which case an explicit CLOBBER
830218334Speter	    will be present.  If we are generating PIC code, the PIC offset
830318334Speter	    table register is preserved across calls.  */
830418334Speter
830518334Speter	 && i != STACK_POINTER_REGNUM
830618334Speter	 && i != FRAME_POINTER_REGNUM
830718334Speter#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
830818334Speter	 && i != HARD_FRAME_POINTER_REGNUM
830918334Speter#endif
831018334Speter#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
831118334Speter	 && ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
831218334Speter#endif
831318334Speter#if defined (PIC_OFFSET_TABLE_REGNUM) && !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
831418334Speter	 && ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
831518334Speter#endif
831618334Speter	 )
831718334Speter	|| global_regs[i])
831818334Speter      SET_HARD_REG_BIT (regs_invalidated_by_call, i);
831918334Speter
832018334Speter  /* Loop over basic blocks.
832118334Speter     Compute the maximum number of qty's needed for each basic block
832218334Speter     (which is 2 for each SET).  */
832318334Speter  insn = f;
832418334Speter  while (insn)
832518334Speter    {
832618334Speter      cse_end_of_basic_block (insn, &val, flag_cse_follow_jumps, after_loop,
832718334Speter			      flag_cse_skip_blocks);
832818334Speter
832918334Speter      /* If this basic block was already processed or has no sets, skip it.  */
833018334Speter      if (val.nsets == 0 || GET_MODE (insn) == QImode)
833118334Speter	{
833218334Speter	  PUT_MODE (insn, VOIDmode);
833318334Speter	  insn = (val.last ? NEXT_INSN (val.last) : 0);
833418334Speter	  val.path_size = 0;
833518334Speter	  continue;
833618334Speter	}
833718334Speter
833818334Speter      cse_basic_block_start = val.low_cuid;
833918334Speter      cse_basic_block_end = val.high_cuid;
834018334Speter      max_qty = val.nsets * 2;
834118334Speter
834218334Speter      if (file)
834318334Speter	fprintf (file, ";; Processing block from %d to %d, %d sets.\n",
834418334Speter		 INSN_UID (insn), val.last ? INSN_UID (val.last) : 0,
834518334Speter		 val.nsets);
834618334Speter
834718334Speter      /* Make MAX_QTY bigger to give us room to optimize
834818334Speter	 past the end of this basic block, if that should prove useful.  */
834918334Speter      if (max_qty < 500)
835018334Speter	max_qty = 500;
835118334Speter
835218334Speter      max_qty += max_reg;
835318334Speter
835418334Speter      /* If this basic block is being extended by following certain jumps,
835518334Speter         (see `cse_end_of_basic_block'), we reprocess the code from the start.
835618334Speter         Otherwise, we start after this basic block.  */
835718334Speter      if (val.path_size > 0)
835818334Speter        cse_basic_block (insn, val.last, val.path, 0);
835918334Speter      else
836018334Speter	{
836118334Speter	  int old_cse_jumps_altered = cse_jumps_altered;
836218334Speter	  rtx temp;
836318334Speter
836418334Speter	  /* When cse changes a conditional jump to an unconditional
836518334Speter	     jump, we want to reprocess the block, since it will give
836618334Speter	     us a new branch path to investigate.  */
836718334Speter	  cse_jumps_altered = 0;
836818334Speter	  temp = cse_basic_block (insn, val.last, val.path, ! after_loop);
836918334Speter	  if (cse_jumps_altered == 0
837018334Speter	      || (flag_cse_follow_jumps == 0 && flag_cse_skip_blocks == 0))
837118334Speter	    insn = temp;
837218334Speter
837318334Speter	  cse_jumps_altered |= old_cse_jumps_altered;
837418334Speter	}
837518334Speter
837618334Speter#ifdef USE_C_ALLOCA
837718334Speter      alloca (0);
837818334Speter#endif
837918334Speter    }
838018334Speter
838118334Speter  /* Tell refers_to_mem_p that qty_const info is not available.  */
838218334Speter  qty_const = 0;
838318334Speter
838418334Speter  if (max_elements_made < n_elements_made)
838518334Speter    max_elements_made = n_elements_made;
838618334Speter
838718334Speter  return cse_jumps_altered || recorded_label_ref;
838818334Speter}
838918334Speter
839018334Speter/* Process a single basic block.  FROM and TO and the limits of the basic
839118334Speter   block.  NEXT_BRANCH points to the branch path when following jumps or
839218334Speter   a null path when not following jumps.
839318334Speter
839418334Speter   AROUND_LOOP is non-zero if we are to try to cse around to the start of a
839518334Speter   loop.  This is true when we are being called for the last time on a
839618334Speter   block and this CSE pass is before loop.c.  */
839718334Speter
839818334Speterstatic rtx
839918334Spetercse_basic_block (from, to, next_branch, around_loop)
840018334Speter     register rtx from, to;
840118334Speter     struct branch_path *next_branch;
840218334Speter     int around_loop;
840318334Speter{
840418334Speter  register rtx insn;
840518334Speter  int to_usage = 0;
840618334Speter  int in_libcall_block = 0;
840718334Speter
840818334Speter  /* Each of these arrays is undefined before max_reg, so only allocate
840918334Speter     the space actually needed and adjust the start below.  */
841018334Speter
841118334Speter  qty_first_reg = (int *) alloca ((max_qty - max_reg) * sizeof (int));
841218334Speter  qty_last_reg = (int *) alloca ((max_qty - max_reg) * sizeof (int));
841318334Speter  qty_mode= (enum machine_mode *) alloca ((max_qty - max_reg) * sizeof (enum machine_mode));
841418334Speter  qty_const = (rtx *) alloca ((max_qty - max_reg) * sizeof (rtx));
841518334Speter  qty_const_insn = (rtx *) alloca ((max_qty - max_reg) * sizeof (rtx));
841618334Speter  qty_comparison_code
841718334Speter    = (enum rtx_code *) alloca ((max_qty - max_reg) * sizeof (enum rtx_code));
841818334Speter  qty_comparison_qty = (int *) alloca ((max_qty - max_reg) * sizeof (int));
841918334Speter  qty_comparison_const = (rtx *) alloca ((max_qty - max_reg) * sizeof (rtx));
842018334Speter
842118334Speter  qty_first_reg -= max_reg;
842218334Speter  qty_last_reg -= max_reg;
842318334Speter  qty_mode -= max_reg;
842418334Speter  qty_const -= max_reg;
842518334Speter  qty_const_insn -= max_reg;
842618334Speter  qty_comparison_code -= max_reg;
842718334Speter  qty_comparison_qty -= max_reg;
842818334Speter  qty_comparison_const -= max_reg;
842918334Speter
843018334Speter  new_basic_block ();
843118334Speter
843218334Speter  /* TO might be a label.  If so, protect it from being deleted.  */
843318334Speter  if (to != 0 && GET_CODE (to) == CODE_LABEL)
843418334Speter    ++LABEL_NUSES (to);
843518334Speter
843618334Speter  for (insn = from; insn != to; insn = NEXT_INSN (insn))
843718334Speter    {
843818334Speter      register enum rtx_code code;
843918334Speter
844018334Speter      /* See if this is a branch that is part of the path.  If so, and it is
844118334Speter	 to be taken, do so.  */
844218334Speter      if (next_branch->branch == insn)
844318334Speter	{
844418334Speter	  enum taken status = next_branch++->status;
844518334Speter	  if (status != NOT_TAKEN)
844618334Speter	    {
844718334Speter	      if (status == TAKEN)
844818334Speter		record_jump_equiv (insn, 1);
844918334Speter	      else
845018334Speter		invalidate_skipped_block (NEXT_INSN (insn));
845118334Speter
845218334Speter	      /* Set the last insn as the jump insn; it doesn't affect cc0.
845318334Speter		 Then follow this branch.  */
845418334Speter#ifdef HAVE_cc0
845518334Speter	      prev_insn_cc0 = 0;
845618334Speter#endif
845718334Speter	      prev_insn = insn;
845818334Speter	      insn = JUMP_LABEL (insn);
845918334Speter	      continue;
846018334Speter	    }
846118334Speter	}
846218334Speter
846318334Speter      code = GET_CODE (insn);
846418334Speter      if (GET_MODE (insn) == QImode)
846518334Speter	PUT_MODE (insn, VOIDmode);
846618334Speter
846718334Speter      if (GET_RTX_CLASS (code) == 'i')
846818334Speter	{
846918334Speter	  /* Process notes first so we have all notes in canonical forms when
847018334Speter	     looking for duplicate operations.  */
847118334Speter
847218334Speter	  if (REG_NOTES (insn))
847318334Speter	    REG_NOTES (insn) = cse_process_notes (REG_NOTES (insn), NULL_RTX);
847418334Speter
847518334Speter	  /* Track when we are inside in LIBCALL block.  Inside such a block,
847618334Speter	     we do not want to record destinations.  The last insn of a
847718334Speter	     LIBCALL block is not considered to be part of the block, since
847818334Speter	     its destination is the result of the block and hence should be
847918334Speter	     recorded.  */
848018334Speter
848118334Speter	  if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
848218334Speter	    in_libcall_block = 1;
848318334Speter	  else if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
848418334Speter	    in_libcall_block = 0;
848518334Speter
848618334Speter	  cse_insn (insn, in_libcall_block);
848718334Speter	}
848818334Speter
848918334Speter      /* If INSN is now an unconditional jump, skip to the end of our
849018334Speter	 basic block by pretending that we just did the last insn in the
849118334Speter	 basic block.  If we are jumping to the end of our block, show
849218334Speter	 that we can have one usage of TO.  */
849318334Speter
849418334Speter      if (simplejump_p (insn))
849518334Speter	{
849618334Speter	  if (to == 0)
849718334Speter	    return 0;
849818334Speter
849918334Speter	  if (JUMP_LABEL (insn) == to)
850018334Speter	    to_usage = 1;
850118334Speter
850218334Speter	  /* Maybe TO was deleted because the jump is unconditional.
850318334Speter	     If so, there is nothing left in this basic block.  */
850418334Speter	  /* ??? Perhaps it would be smarter to set TO
850518334Speter	     to whatever follows this insn,
850618334Speter	     and pretend the basic block had always ended here.  */
850718334Speter	  if (INSN_DELETED_P (to))
850818334Speter	    break;
850918334Speter
851018334Speter	  insn = PREV_INSN (to);
851118334Speter	}
851218334Speter
851318334Speter      /* See if it is ok to keep on going past the label
851418334Speter	 which used to end our basic block.  Remember that we incremented
851518334Speter	 the count of that label, so we decrement it here.  If we made
851618334Speter	 a jump unconditional, TO_USAGE will be one; in that case, we don't
851718334Speter	 want to count the use in that jump.  */
851818334Speter
851918334Speter      if (to != 0 && NEXT_INSN (insn) == to
852018334Speter	  && GET_CODE (to) == CODE_LABEL && --LABEL_NUSES (to) == to_usage)
852118334Speter	{
852218334Speter	  struct cse_basic_block_data val;
852318334Speter	  rtx prev;
852418334Speter
852518334Speter	  insn = NEXT_INSN (to);
852618334Speter
852718334Speter	  if (LABEL_NUSES (to) == 0)
852818334Speter	    insn = delete_insn (to);
852918334Speter
853018334Speter	  /* If TO was the last insn in the function, we are done.  */
853118334Speter	  if (insn == 0)
853218334Speter	    return 0;
853318334Speter
853418334Speter	  /* If TO was preceded by a BARRIER we are done with this block
853518334Speter	     because it has no continuation.  */
853618334Speter	  prev = prev_nonnote_insn (to);
853718334Speter	  if (prev && GET_CODE (prev) == BARRIER)
853818334Speter	    return insn;
853918334Speter
854018334Speter	  /* Find the end of the following block.  Note that we won't be
854118334Speter	     following branches in this case.  */
854218334Speter	  to_usage = 0;
854318334Speter	  val.path_size = 0;
854418334Speter	  cse_end_of_basic_block (insn, &val, 0, 0, 0);
854518334Speter
854618334Speter	  /* If the tables we allocated have enough space left
854718334Speter	     to handle all the SETs in the next basic block,
854818334Speter	     continue through it.  Otherwise, return,
854918334Speter	     and that block will be scanned individually.  */
855018334Speter	  if (val.nsets * 2 + next_qty > max_qty)
855118334Speter	    break;
855218334Speter
855318334Speter	  cse_basic_block_start = val.low_cuid;
855418334Speter	  cse_basic_block_end = val.high_cuid;
855518334Speter	  to = val.last;
855618334Speter
855718334Speter	  /* Prevent TO from being deleted if it is a label.  */
855818334Speter	  if (to != 0 && GET_CODE (to) == CODE_LABEL)
855918334Speter	    ++LABEL_NUSES (to);
856018334Speter
856118334Speter	  /* Back up so we process the first insn in the extension.  */
856218334Speter	  insn = PREV_INSN (insn);
856318334Speter	}
856418334Speter    }
856518334Speter
856618334Speter  if (next_qty > max_qty)
856718334Speter    abort ();
856818334Speter
856918334Speter  /* If we are running before loop.c, we stopped on a NOTE_INSN_LOOP_END, and
857018334Speter     the previous insn is the only insn that branches to the head of a loop,
857118334Speter     we can cse into the loop.  Don't do this if we changed the jump
857218334Speter     structure of a loop unless we aren't going to be following jumps.  */
857318334Speter
857418334Speter  if ((cse_jumps_altered == 0
857518334Speter       || (flag_cse_follow_jumps == 0 && flag_cse_skip_blocks == 0))
857618334Speter      && around_loop && to != 0
857718334Speter      && GET_CODE (to) == NOTE && NOTE_LINE_NUMBER (to) == NOTE_INSN_LOOP_END
857818334Speter      && GET_CODE (PREV_INSN (to)) == JUMP_INSN
857918334Speter      && JUMP_LABEL (PREV_INSN (to)) != 0
858018334Speter      && LABEL_NUSES (JUMP_LABEL (PREV_INSN (to))) == 1)
858118334Speter    cse_around_loop (JUMP_LABEL (PREV_INSN (to)));
858218334Speter
858318334Speter  return to ? NEXT_INSN (to) : 0;
858418334Speter}
858518334Speter
858618334Speter/* Count the number of times registers are used (not set) in X.
858718334Speter   COUNTS is an array in which we accumulate the count, INCR is how much
858818334Speter   we count each register usage.
858918334Speter
859018334Speter   Don't count a usage of DEST, which is the SET_DEST of a SET which
859118334Speter   contains X in its SET_SRC.  This is because such a SET does not
859218334Speter   modify the liveness of DEST.  */
859318334Speter
859418334Speterstatic void
859518334Spetercount_reg_usage (x, counts, dest, incr)
859618334Speter     rtx x;
859718334Speter     int *counts;
859818334Speter     rtx dest;
859918334Speter     int incr;
860018334Speter{
860118334Speter  enum rtx_code code;
860218334Speter  char *fmt;
860318334Speter  int i, j;
860418334Speter
860518334Speter  if (x == 0)
860618334Speter    return;
860718334Speter
860818334Speter  switch (code = GET_CODE (x))
860918334Speter    {
861018334Speter    case REG:
861118334Speter      if (x != dest)
861218334Speter	counts[REGNO (x)] += incr;
861318334Speter      return;
861418334Speter
861518334Speter    case PC:
861618334Speter    case CC0:
861718334Speter    case CONST:
861818334Speter    case CONST_INT:
861918334Speter    case CONST_DOUBLE:
862018334Speter    case SYMBOL_REF:
862118334Speter    case LABEL_REF:
862218334Speter    case CLOBBER:
862318334Speter      return;
862418334Speter
862518334Speter    case SET:
862618334Speter      /* Unless we are setting a REG, count everything in SET_DEST.  */
862718334Speter      if (GET_CODE (SET_DEST (x)) != REG)
862818334Speter	count_reg_usage (SET_DEST (x), counts, NULL_RTX, incr);
862918334Speter
863018334Speter      /* If SRC has side-effects, then we can't delete this insn, so the
863118334Speter	 usage of SET_DEST inside SRC counts.
863218334Speter
863318334Speter	 ??? Strictly-speaking, we might be preserving this insn
863418334Speter	 because some other SET has side-effects, but that's hard
863518334Speter	 to do and can't happen now.  */
863618334Speter      count_reg_usage (SET_SRC (x), counts,
863718334Speter		       side_effects_p (SET_SRC (x)) ? NULL_RTX : SET_DEST (x),
863818334Speter		       incr);
863918334Speter      return;
864018334Speter
864118334Speter    case CALL_INSN:
864218334Speter      count_reg_usage (CALL_INSN_FUNCTION_USAGE (x), counts, NULL_RTX, incr);
864318334Speter
864418334Speter      /* ... falls through ...  */
864518334Speter    case INSN:
864618334Speter    case JUMP_INSN:
864718334Speter      count_reg_usage (PATTERN (x), counts, NULL_RTX, incr);
864818334Speter
864918334Speter      /* Things used in a REG_EQUAL note aren't dead since loop may try to
865018334Speter	 use them.  */
865118334Speter
865218334Speter      count_reg_usage (REG_NOTES (x), counts, NULL_RTX, incr);
865318334Speter      return;
865418334Speter
865518334Speter    case EXPR_LIST:
865618334Speter    case INSN_LIST:
865718334Speter      if (REG_NOTE_KIND (x) == REG_EQUAL
865818334Speter	  || GET_CODE (XEXP (x,0)) == USE)
865918334Speter	count_reg_usage (XEXP (x, 0), counts, NULL_RTX, incr);
866018334Speter      count_reg_usage (XEXP (x, 1), counts, NULL_RTX, incr);
866118334Speter      return;
866218334Speter    }
866318334Speter
866418334Speter  fmt = GET_RTX_FORMAT (code);
866518334Speter  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
866618334Speter    {
866718334Speter      if (fmt[i] == 'e')
866818334Speter	count_reg_usage (XEXP (x, i), counts, dest, incr);
866918334Speter      else if (fmt[i] == 'E')
867018334Speter	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
867118334Speter	  count_reg_usage (XVECEXP (x, i, j), counts, dest, incr);
867218334Speter    }
867318334Speter}
867418334Speter
867518334Speter/* Scan all the insns and delete any that are dead; i.e., they store a register
867618334Speter   that is never used or they copy a register to itself.
867718334Speter
867818334Speter   This is used to remove insns made obviously dead by cse.  It improves the
867918334Speter   heuristics in loop since it won't try to move dead invariants out of loops
868018334Speter   or make givs for dead quantities.  The remaining passes of the compilation
868118334Speter   are also sped up.  */
868218334Speter
868318334Spetervoid
868418334Speterdelete_dead_from_cse (insns, nreg)
868518334Speter     rtx insns;
868618334Speter     int nreg;
868718334Speter{
868818334Speter  int *counts = (int *) alloca (nreg * sizeof (int));
868918334Speter  rtx insn, prev;
869018334Speter  rtx tem;
869118334Speter  int i;
869218334Speter  int in_libcall = 0;
869318334Speter
869418334Speter  /* First count the number of times each register is used.  */
869518334Speter  bzero ((char *) counts, sizeof (int) * nreg);
869618334Speter  for (insn = next_real_insn (insns); insn; insn = next_real_insn (insn))
869718334Speter    count_reg_usage (insn, counts, NULL_RTX, 1);
869818334Speter
869918334Speter  /* Go from the last insn to the first and delete insns that only set unused
870018334Speter     registers or copy a register to itself.  As we delete an insn, remove
870118334Speter     usage counts for registers it uses.  */
870218334Speter  for (insn = prev_real_insn (get_last_insn ()); insn; insn = prev)
870318334Speter    {
870418334Speter      int live_insn = 0;
870518334Speter
870618334Speter      prev = prev_real_insn (insn);
870718334Speter
870818334Speter      /* Don't delete any insns that are part of a libcall block.
870918334Speter	 Flow or loop might get confused if we did that.  Remember
871018334Speter	 that we are scanning backwards.  */
871118334Speter      if (find_reg_note (insn, REG_RETVAL, NULL_RTX))
871218334Speter	in_libcall = 1;
871318334Speter
871418334Speter      if (in_libcall)
871518334Speter	live_insn = 1;
871618334Speter      else if (GET_CODE (PATTERN (insn)) == SET)
871718334Speter	{
871818334Speter	  if (GET_CODE (SET_DEST (PATTERN (insn))) == REG
871918334Speter	      && SET_DEST (PATTERN (insn)) == SET_SRC (PATTERN (insn)))
872018334Speter	    ;
872118334Speter
872218334Speter#ifdef HAVE_cc0
872318334Speter	  else if (GET_CODE (SET_DEST (PATTERN (insn))) == CC0
872418334Speter		   && ! side_effects_p (SET_SRC (PATTERN (insn)))
872518334Speter		   && ((tem = next_nonnote_insn (insn)) == 0
872618334Speter		       || GET_RTX_CLASS (GET_CODE (tem)) != 'i'
872718334Speter		       || ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
872818334Speter	    ;
872918334Speter#endif
873018334Speter	  else if (GET_CODE (SET_DEST (PATTERN (insn))) != REG
873118334Speter		   || REGNO (SET_DEST (PATTERN (insn))) < FIRST_PSEUDO_REGISTER
873218334Speter		   || counts[REGNO (SET_DEST (PATTERN (insn)))] != 0
873318334Speter		   || side_effects_p (SET_SRC (PATTERN (insn))))
873418334Speter	    live_insn = 1;
873518334Speter	}
873618334Speter      else if (GET_CODE (PATTERN (insn)) == PARALLEL)
873718334Speter	for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
873818334Speter	  {
873918334Speter	    rtx elt = XVECEXP (PATTERN (insn), 0, i);
874018334Speter
874118334Speter	    if (GET_CODE (elt) == SET)
874218334Speter	      {
874318334Speter		if (GET_CODE (SET_DEST (elt)) == REG
874418334Speter		    && SET_DEST (elt) == SET_SRC (elt))
874518334Speter		  ;
874618334Speter
874718334Speter#ifdef HAVE_cc0
874818334Speter		else if (GET_CODE (SET_DEST (elt)) == CC0
874918334Speter			 && ! side_effects_p (SET_SRC (elt))
875018334Speter			 && ((tem = next_nonnote_insn (insn)) == 0
875118334Speter			     || GET_RTX_CLASS (GET_CODE (tem)) != 'i'
875218334Speter			     || ! reg_referenced_p (cc0_rtx, PATTERN (tem))))
875318334Speter		  ;
875418334Speter#endif
875518334Speter		else if (GET_CODE (SET_DEST (elt)) != REG
875618334Speter			 || REGNO (SET_DEST (elt)) < FIRST_PSEUDO_REGISTER
875718334Speter			 || counts[REGNO (SET_DEST (elt))] != 0
875818334Speter			 || side_effects_p (SET_SRC (elt)))
875918334Speter		  live_insn = 1;
876018334Speter	      }
876118334Speter	    else if (GET_CODE (elt) != CLOBBER && GET_CODE (elt) != USE)
876218334Speter	      live_insn = 1;
876318334Speter	  }
876418334Speter      else
876518334Speter	live_insn = 1;
876618334Speter
876718334Speter      /* If this is a dead insn, delete it and show registers in it aren't
876818334Speter	 being used.  */
876918334Speter
877018334Speter      if (! live_insn)
877118334Speter	{
877218334Speter	  count_reg_usage (insn, counts, NULL_RTX, -1);
877318334Speter	  delete_insn (insn);
877418334Speter	}
877518334Speter
877618334Speter      if (find_reg_note (insn, REG_LIBCALL, NULL_RTX))
877718334Speter	in_libcall = 0;
877818334Speter    }
877918334Speter}
8780