123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403 |
- /* Common subexpression elimination for GNU compiler.
- Copyright (C) 1987 Free Software Foundation, Inc.
- This file is part of GNU CC.
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY. No author or distributor
- accepts responsibility to anyone for the consequences of using it
- or for whether it serves any particular purpose or works at all,
- unless he says so in writing. Refer to the GNU CC General Public
- License for full details.
- Everyone is granted permission to copy, modify and redistribute
- GNU CC, but only under the conditions described in the
- GNU CC General Public License. A copy of this license is
- supposed to have been given to you along with GNU CC so you
- can know your rights and responsibilities. It should be in a
- file named COPYING. Among other things, the copyright notice
- and this notice must be preserved on all copies. */
- #include "config.h"
- #include "rtl.h"
- #include "insn-config.h"
- #include "regs.h"
- /* The basic idea of common subexpression elimination is to go
- through the code, keeping a record of expressions that would
- have the same value at the current scan point, and replacing
- expressions encountered with the cheapest equivalent expression.
- It is too complicated to keep track of the different possibilities
- when control paths merge; so, at each label, we forget all that is
- known and start fresh. This can be described as processing each
- basic block separately. Note, however, that these are not quite
- the same as the basic blocks found by a later pass and used for
- data flow analysis and register packing. We do not need to start fresh
- after a conditional jump instruction if there is no label there.
- We use two data structures to record the equivalent expressions:
- a hash table for most expressions, and several vectors together
- with "quantity numbers" to record equivalent (pseudo) registers.
- The use of the special data structure for registers is desirable
- because it is faster. It is possible because registers references
- contain a fairly small number, the register number, taken from
- a contiguously allocated series, and two register references are
- identical if they have the same number. General expressions
- do not have any such thing, so the only way to retrieve the
- information recorded on an expression other than a register
- is to keep it in a hash table.
- Registers and "quantity numbers":
-
- At the start of each basic block, all of the (hardware and pseudo)
- registers used in the function are given distinct quantity
- numbers to indicate their contents. During scan, when the code
- copies one register into another, we copy the quantity number.
- When a register is loaded in any other way, we allocate a new
- quantity number to describe the value generated by this operation.
- `reg_qty' records what quantity a register is currently thought
- of as containing.
- We also maintain a bidirectional chain of registers for each
- quantity number. `qty_first_reg', `qty_last_reg',
- `reg_next_eqv' and `reg_prev_eqv' hold these chains.
- The first register in a chain is the one whose lifespan is least local.
- Among equals, it is the one that was seen first.
- We replace any equivalent register with that one.
- Constants and quantity numbers
- When a quantity has a known constant value, that value is stored
- in the appropriate element of qty_const. This is in addition to
- putting the constant in the hash table as is usual for non-regs.
- Regs are preferred to constants as they are to everything else,
- but expressions containing constants can be simplified, by fold_rtx.
- Other expressions:
- To record known equivalences among expressions in general
- we use a hash table called `table'. It has a fixed number of buckets
- that contain chains of `struct table_elt' elements for expressions.
- These chains connect the elements whose expressions have the same
- hash codes.
- Other chains through the same elements connect the elements which
- currently have equivalent values.
- Register references in an expression are canonicalized before hashing
- the expression. This is done using `reg_qty' and `qty_first_reg'.
- The hash code of a register reference is computed using the quantity
- number, not the register number.
- When the value of an expression changes, it is necessary to remove from the
- hash table not just that expression but all expressions whose values
- could be different as a result.
- 1. If the value changing is in memory, except in special cases
- ANYTHING referring to memory could be changed. That is because
- nobody knows where a pointer does not point.
- The function `invalidate_memory' removes what is necessary.
- The special cases are when the address is constant or is
- a constant plus a fixed register such as the frame pointer
- or a static chain pointer. When such addresses are stored in,
- we can tell exactly which other such addresses must be invalidated
- due to overlap. `invalidate' does this.
- All expressions that refer to non-constant
- memory addresses are also invalidated. `invalidate_memory' does this.
- 2. If the value changing is a register, all expressions
- containing references to that register, and only those,
- must be removed.
- Because searching the entire hash table for expressions that contain
- a register is very slow, we try to figure out when it isn't necessary.
- Precisely, this is necessary only when there expressions have been
- entered in the hash table using this register, and then the value has
- changed, and then another expression wants to be added to refer to
- teh register's new value. This sequence of circumstances is rare
- within any one basic block.
- The vectors `reg_tick' and `reg_in_table' are used to detect this case.
- reg_tick[i] is incremented whenever a value is stored in register i.
- reg_in_table[i] holds -1 if no references to register i have been
- entered in the table; otherwise, it contains the value reg_tick[i] had
- when the references were entered. If we want to enter a reference
- and reg_in_table[i] != reg_tick[i], we must scan and remove old references.
- Until we want to enter a new entry, the mere fact that the twovectors
- don't match makes the entries be ignored if anyone tries to match them.
- Registers themselves are entered in the hash table as well as in
- the equivalent-register chains. However, the vectors `reg_tick'
- and `reg_in_table' do not apply to expressions which are simple
- register references. These expressions are removed from the table
- immediately when they become invalid, and this can be done even if
- we do not immediately search for all the expressions that refer to
- the register.
- A CLOBBER rtx in an instruction invalidates its operand for further
- reuse. A CLOBBER rtx whose operand is 0 (a null pointer)
- invalidates everything that resides in memory.
- Related expressions:
- Constant expressions that differ only by an additive integer
- are called related. When a constant expression is put in
- the table, the related expression with no constant term
- is also entered. These are made to point at each other
- so that it is possible to find out if there exists any
- register equivalent to an expression related to a given expression. */
-
- /* One plus largest register number used in this function. */
- static int max_reg;
- /* Length of vectors indexed by quantity number.
- We know in advance we will not need a quantity number this big. */
- static int max_qty;
- /* Next quantity number to be allocated.
- This is 1 + the largest number needed so far. */
- static int next_qty;
- /* Indexed by quantity number, gives the first (or last) (pseudo) register
- in the chain of registers that currently contain this quantity. */
- static int *qty_first_reg;
- static int *qty_last_reg;
- /* Indexed by quantity number, gives the rtx of the constant value of the
- quantity, or zero if it does not have a known value. */
- static rtx *qty_const;
- /* Value stored in CC0 by previous insn:
- 0 if previous insn didn't store in CC0.
- else 100 + (M&7)<<3 + (N&7)
- where M is 1, 0 or -1 if result was pos, zero or neg as signed number
- and N is 1, 0 or -1 if result was pos, zero or neg as unsigned number. */
- static int prev_insn_cc0;
- /* Previous actual insn. 0 if at first insn of basic block. */
- static rtx prev_insn;
- /* Index by (pseudo) register number, gives the quantity number
- of the register's current contents. */
- static int *reg_qty;
- /* Index by (pseudo) register number, gives the number of the next
- (pseudo) register in the chain of registers sharing the same value.
- Or -1 if this register is at the end of the chain. */
- static int *reg_next_eqv;
- /* Index by (pseudo) register number, gives the number of the previous
- (pseudo) register in the chain of registers sharing the same value.
- Or -1 if this register is at the beginning of the chain. */
- static int *reg_prev_eqv;
- /* Index by (pseudo) register number, gives the latest rtx
- to use to insert a ref to that register. */
- static rtx *reg_rtx;
- /* Index by (pseudo) register number, gives the number of times
- that register has been altered in the current basic block. */
- static int *reg_tick;
- /* Index by (pseudo) register number, gives the reg_tick value at which
- rtx's containing this register are valid in the hash table.
- If this does not equal the current reg_tick value, such expressions
- existing in the hash table are invalid.
- If this is -1, no expressions containing this register have been
- entered in the table. */
- static int *reg_in_table;
- /* Two vectors of max_reg ints:
- one containing all -1's; in the other, element i contains i.
- These are used to initialize various other vectors fast. */
- static int *all_minus_one;
- static int *consec_ints;
- /* Indexed by hardware register number, contains nonzero
- for registers that may be clobbered by subroutine calls
- (and also for the fixed-use registers,
- which we must check for and refrain from invalidating). */
- static char call_clobbers_reg[] = CALL_USED_REGISTERS;
- /* UID of insn that ends the basic block currently being cse-processed. */
- static int cse_basic_block_end;
- /* Nonzero if cse has altered conditional jump insns
- in such a way that jump optimization should be redone. */
- static int cse_jumps_altered;
- /* canon_hash stores 1 in do_not_record
- if it notices a reference to CC0, CC1 or PC. */
- static int do_not_record;
- /* canon_hash stores 1 in hash_arg_in_memory
- if it notices a reference to memory within the expression being hashed. */
- static int hash_arg_in_memory;
- /* The hash table contains buckets which are chains of `struct table_elt's,
- each recording one expression's information.
- That expression is in the `exp' field.
- Those elements with the same hash code are chained in both directions
- through the `next_same_hash' and `prev_same_hash' fields.
- Each set of expressions with equivalent values
- are on a two-way chain through the `next_same_value'
- and `prev_same_value' fields, and all point with
- the `first_same_value' field at the first element in
- that chain. The chain is in order of increasing cost.
- Each element's cost value is in its `cost' field.
- The `in_memory' field is nonzero for elements that
- involve any reference to memory. These elements are removed
- whenever a write is done to an unidentified location in memory.
- To be safe, we assume that a memory address is unidentified unless
- the address is either a symbol constant or a constant plus
- the frame pointer or argument pointer.
- The `related_value' field is used to connect related expressions
- (that differ by adding an integer).
- The related expressions are chained in a circular fashion.
- `related_value' is zero for expressions for which this
- chain is not useful. */
- struct table_elt
- {
- rtx exp;
- struct table_elt *next_same_hash;
- struct table_elt *prev_same_hash;
- struct table_elt *next_same_value;
- struct table_elt *prev_same_value;
- struct table_elt *first_same_value;
- struct table_elt *related_value;
- int cost;
- char in_memory;
- };
- #define HASH(x) (canon_hash (x) % NBUCKETS)
- /* We don't want a lot of buckets, because we rarely have very many
- things stored in the hash table, and a lot of buckets slows
- down a lot of loops that happen frequently. */
- #define NBUCKETS 31
- static struct table_elt *table[NBUCKETS];
- /* Chain of `struct table_elt's made so far for this function
- but currently removed from the table. */
- static struct table_elt *free_element_chain;
- /* Number of `struct table_elt' structures made so far for this function. */
- static int n_elements_made;
- /* Maximum value `n_elements_made' has had so far in this compilation
- for functions previously processed. */
- static int max_elements_made;
- /* Bits describing what kind of values in memory must be invalidated
- for a particular instruction. If all three bits are zero,
- no memory refs need to be invalidated. Each bit is more powerful
- than the preceding ones, and if a bit is set then the preceding
- bits are also set.
- Here is how the bits are set.
- Writing at a fixed address invalidates only variable addresses,
- writing in a structure element at variable address
- invalidates all but scalar variables,
- and writing in anything else at variable address invalidates everything. */
- struct write_data
- {
- int var : 1; /* Invalidate variable addresses. */
- int nonscalar : 1; /* Invalidate all but scalar variables. */
- int all : 1; /* Invalidate all memory refs. */
- };
- static struct table_elt *lookup ();
- static void free_element ();
- static void remove_invalid_refs ();
- static int exp_equiv_p ();
- int refers_to_p ();
- int refers_to_mem_p ();
- static void invalidate_from_clobbers ();
- static int safe_hash ();
- static int get_integer_term ();
- static rtx get_related_value ();
- static void note_mem_written ();
- /* Return an estimate of the cost of computing rtx X.
- The only use of this is to compare the costs of two expressions
- to decide whether to replace one with the other. */
- static int
- rtx_cost (x)
- rtx x;
- {
- register int i;
- register RTX_CODE code = GET_CODE (x);
- register char *fmt;
- register int total;
- switch (code)
- {
- case REG:
- return 1;
- case SUBREG:
- return 2;
- CONST_COSTS (x, code);
- }
- total = 2;
- /* Compare the elements. If any pair of corresponding elements
- fail to match, return 0 for the whole things. */
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- total += rtx_cost (XEXP (x, i));
- return total;
- }
- /* Clear the hash table and initialize each register with its own quantity,
- for a new basic block. */
- static void
- new_basic_block ()
- {
- register int i;
- register int vecsize = max_reg * sizeof (rtx);
- next_qty = max_reg;
- bzero (reg_rtx, vecsize);
- bzero (reg_tick, vecsize);
- bcopy (all_minus_one, reg_in_table, vecsize);
- bcopy (all_minus_one, reg_next_eqv, vecsize);
- bcopy (all_minus_one, reg_prev_eqv, vecsize);
- bcopy (consec_ints, reg_qty, vecsize);
- for (i = 0; i < max_qty; i++)
- {
- qty_first_reg[i] = i;
- qty_last_reg[i] = i;
- qty_const[i] = 0;
- }
- for (i = 0; i < NBUCKETS; i++)
- {
- register struct table_elt *this, *next;
- for (this = table[i]; this; this = next)
- {
- next = this->next_same_hash;
- free_element (this);
- }
- }
- bzero (table, sizeof table);
- prev_insn_cc0 = 0;
- prev_insn = 0;
- }
- /* Say that register REG contains a quantity not in any register before. */
- static void
- make_new_qty (reg)
- register int reg;
- {
- register int q;
- q = reg_qty[reg] = next_qty++;
- qty_first_reg[q] = reg;
- qty_last_reg[q] = reg;
- }
- /* Make reg NEW equivalent to reg OLD.
- OLD is not changing; NEW is. */
- static void
- make_regs_eqv (new, old)
- register int new, old;
- {
- register int lastr, firstr;
- register int q;
- q = reg_qty[new] = reg_qty[old];
- firstr = qty_first_reg[q];
- /* Prefer pseudo regs to hard regs with the same value.
- Among pseudos, if NEW will live longer than any other reg of the same qty,
- and that is beyond the current basic block,
- make it the new canonical replacement for this qty. */
- if (new >= FIRST_PSEUDO_REGISTER
- && (firstr < FIRST_PSEUDO_REGISTER
- || ((regno_last_uid[new] > cse_basic_block_end)
- &&
- (regno_last_uid[new] > regno_last_uid[firstr]))))
- {
- lastr = qty_first_reg[q];
- reg_prev_eqv[lastr] = new;
- reg_next_eqv[new] = lastr;
- reg_prev_eqv[new] = -1;
- qty_first_reg[q] = new;
- }
- else
- {
- lastr = qty_last_reg[q];
- reg_next_eqv[lastr] = new;
- reg_prev_eqv[new] = lastr;
- reg_next_eqv[new] = -1;
- qty_last_reg[q] = new;
- }
- }
- /* Discard the records of what is in register REG. */
- static void
- reg_invalidate (reg)
- register int reg;
- {
- register int n = reg_next_eqv[reg];
- register int p = reg_prev_eqv[reg];
- register int q = reg_qty[reg];
- reg_tick[reg]++;
- if (q == reg)
- return; /* Save time if already invalid */
- if (n != -1)
- reg_prev_eqv[n] = p;
- else
- qty_last_reg[q] = p;
- if (p != -1)
- reg_next_eqv[p] = n;
- else
- qty_first_reg[q] = n;
- reg_qty[reg] = reg;
- qty_first_reg[reg] = reg;
- qty_last_reg[reg] = reg;
- reg_next_eqv[reg] = -1;
- reg_prev_eqv[reg] = -1;
- }
- /* Remove any invalid expressions from the hash table
- that refer to any of the registers contained in expression X.
- Make sure that newly inserted references to those registers
- as subexpressions will be considered valid.
- mention_regs is not called when a register itself
- is being stored in the table. */
- static void
- mention_regs (x)
- rtx x;
- {
- register RTX_CODE code = GET_CODE (x);
- register int i;
- register char *fmt;
- if (code == REG)
- {
- register int regno = REGNO (x);
- reg_rtx[regno] = x;
- if (reg_in_table[regno] >= 0 && reg_in_table[regno] != reg_tick[regno])
- remove_invalid_refs (regno);
- reg_in_table[regno] = reg_tick[regno];
- return;
- }
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- mention_regs (XEXP (x, i));
- }
- /* Update the register quantities for inserting X into the hash table
- with a value equivalent to CLASSP.
- If MODIFIED is nonzero, X is a destination; it is being modified.
- Note that reg_invalidate should be called on a register
- before insert_regs is done on that register with MODIFIED != 0. */
- static int
- insert_regs (x, classp, modified)
- rtx x;
- struct table_elt *classp;
- int modified;
- {
- if (GET_CODE (x) == REG)
- {
- register int regno = REGNO (x);
- reg_rtx[regno] = x;
- if (modified || reg_qty[regno] == regno)
- {
- if (classp && GET_CODE (classp->exp) == REG)
- {
- make_regs_eqv (regno, REGNO (classp->exp));
- /* Make sure reg_rtx is set up even for regs
- not explicitly set (such as function value). */
- reg_rtx[REGNO (classp->exp)] = classp->exp;
- }
- else
- make_new_qty (regno);
- return 1;
- }
- }
- else
- mention_regs (x);
- return 0;
- }
- /* Look in or update the hash table. */
- /* Put the element ELT on the list of free elements. */
- static void
- free_element (elt)
- struct table_elt *elt;
- {
- elt->next_same_hash = free_element_chain;
- free_element_chain = elt;
- }
- /* Return an element that is free for use. */
- static struct table_elt *
- get_element ()
- {
- struct table_elt *elt = free_element_chain;
- if (elt)
- {
- free_element_chain = elt->next_same_hash;
- return elt;
- }
- n_elements_made++;
- return (struct table_elt *) oballoc (sizeof (struct table_elt));
- }
- /* Remove table element ELT from use in the table.
- HASH is its hash code, made using the HASH macro.
- It's an argument because often that is known in advance
- and we save much time not recomputing it. */
- static void
- remove (elt, hash)
- register struct table_elt *elt;
- int hash;
- {
- if (elt == 0)
- return;
- /* Mark this element as removed. See cse_insn. */
- elt->first_same_value = 0;
- /* Remove the table element from its equivalence class. */
-
- {
- register struct table_elt *prev = elt->prev_same_value;
- register struct table_elt *next = elt->next_same_value;
- if (next) next->prev_same_value = prev;
- if (prev)
- prev->next_same_value = next;
- else
- {
- register struct table_elt *newfirst = next;
- while (next)
- {
- next->first_same_value = newfirst;
- next = next->next_same_value;
- }
- }
- }
- /* Remove the table element from its hash bucket. */
- {
- register struct table_elt *prev = elt->prev_same_hash;
- register struct table_elt *next = elt->next_same_hash;
- if (next) next->prev_same_hash = prev;
- if (prev)
- prev->next_same_hash = next;
- else
- table[hash] = next;
- }
- /* Remove the table element from its related-value circular chain. */
- if (elt->related_value != 0 && elt->related_value != elt)
- {
- register struct table_elt *p = elt->related_value;
- while (p->related_value != elt)
- p = p->related_value;
- p->related_value = elt->related_value;
- if (p->related_value == p)
- p->related_value = 0;
- }
- free_element (elt);
- }
- /* Look up X in the hash table and return its table element,
- or 0 if X is not in the table.
- Here we are satisfied to find an expression equivalent to X. */
- static struct table_elt *
- lookup (x, hash)
- rtx x;
- int hash;
- {
- register struct table_elt *p;
- for (p = table[hash]; p; p = p->next_same_hash)
- if (x == p->exp || exp_equiv_p (x, p->exp, 1))
- return p;
- return 0;
- }
- /* Look for an expression equivalent to X and of the form (CODE Y).
- If one is found, return Y. */
- static rtx
- lookup_as_function (x, code)
- rtx x;
- enum rtx_code code;
- {
- register struct table_elt *p = lookup (x, safe_hash (x) % NBUCKETS);
- if (p == 0)
- return 0;
- for (p = p->first_same_value; p; p = p->next_same_value)
- {
- if (GET_CODE (p->exp) == code
- /* Make sure this is a valid entry in the table. */
- && (exp_equiv_p (XEXP (p->exp, 0), XEXP (p->exp, 0))))
- return XEXP (p->exp, 0);
- }
-
- return 0;
- }
- /* Insert X in the hash table, assuming HASH is its hash code
- and CLASSP is the current first element of the class it should go in
- (or 0 if a new class should be made).
- It is inserted at the proper position to keep the class in
- the order cheapest first.
- For elements of equal cheapness, the most recent one
- goes in front, except that the first element in the list
- remains first unless a cheaper element is added.
- The in_memory field in the hash table element is set to 0.
- The caller must set it nonzero if appropriate.
- You should call insert_regs (X, CLASSP, MODIFY) before calling here,
- and if insert_regs returns a nonzero value
- you must then recompute its hash code before calling here.
- If necessary, update table showing constant values of quantities. */
- #define CHEAPER(X,Y) \
- (((X)->cost < (Y)->cost) || \
- (GET_CODE ((X)->exp) == REG && GET_CODE ((Y)->exp) == REG \
- && (regno_last_uid[REGNO ((X)->exp)] \
- > cse_basic_block_end) \
- && (regno_last_uid[REGNO ((X)->exp)] \
- > regno_last_uid[REGNO ((Y)->exp)])))
- static struct table_elt *
- insert (x, classp, hash)
- register rtx x;
- register struct table_elt *classp;
- int hash;
- {
- register struct table_elt *elt;
- /* Put an element for X into the right hash bucket. */
- elt = get_element ();
- elt->exp = x;
- elt->cost = rtx_cost (x);
- elt->next_same_value = 0;
- elt->prev_same_value = 0;
- elt->next_same_hash = table[hash];
- elt->prev_same_hash = 0;
- elt->related_value = 0;
- elt->in_memory = 0;
- if (table[hash])
- table[hash]->prev_same_hash = elt;
- table[hash] = elt;
- /* Put it into the proper value-class. */
- if (classp)
- {
- if (CHEAPER (elt, classp))
- /** Insert at the head of the class */
- {
- register struct table_elt *p;
- elt->next_same_value = classp;
- classp->prev_same_value = elt;
- elt->first_same_value = elt;
- for (p = classp; p; p = p->next_same_value)
- p->first_same_value = elt;
- }
- else
- {
- /* Insert not at head of the class. */
- /* Put it after the last element cheaper than X. */
- register struct table_elt *p, *next;
- for (p = classp; (next = p->next_same_value) && CHEAPER (p, elt);
- p = next);
- elt->next_same_value = next;
- if (next)
- next->prev_same_value = elt;
- elt->prev_same_value = p;
- p->next_same_value = elt;
- elt->first_same_value = classp;
- }
- }
- else
- elt->first_same_value = elt;
- if (GET_CODE (x) == CONST_INT)
- {
- if (GET_CODE (elt->first_same_value->exp) == REG)
- qty_const[reg_qty[REGNO (elt->first_same_value->exp)]] = x;
- }
- if (GET_CODE (x) == REG)
- {
- if (elt->next_same_value != 0
- && GET_CODE (elt->next_same_value->exp) == CONST_INT)
- qty_const[reg_qty[REGNO (x)]] = elt->next_same_value->exp;
- if (GET_CODE (elt->first_same_value->exp) == CONST_INT)
- qty_const[reg_qty[REGNO (x)]] = elt->first_same_value->exp;
- }
- /* If this is a constant with symbolic value,
- and it has a term with an explicit integer value,
- link it up with related expressions. */
- if (GET_CODE (x) == CONST)
- {
- rtx subexp = get_related_value (x);
- int subhash;
- struct table_elt *subelt;
- if (subexp != 0)
- {
- /* Get the integer-free subexpression in the hash table. */
- subhash = safe_hash (subexp) % NBUCKETS;
- subelt = lookup (subexp, subhash);
- if (subelt == 0)
- subelt = insert (subexp, 0, subhash);
- /* Initialize SUBELT's circular chain if it has none. */
- if (subelt->related_value == 0)
- subelt->related_value = subelt;
- /* Put new ELT into SUBELT's circular chain. */
- elt->related_value = subelt->related_value;
- subelt->related_value = elt;
- }
- }
- return elt;
- }
- /* Remove from the hash table all expressions that
- refer to expression X. X is either a register
- or a memory reference with nonvarying address
- (because, when a memory reference with a varying address is stored in,
- all memory references are removed by invalidate_memory
- so specific invalidation is superfluous).
- A nonvarying address may be just a register or just
- a symbol reference, or it may be either of those plus
- a numeric offset. */
- static void
- invalidate (x)
- rtx x;
- {
- register int i;
- register struct table_elt *p;
- register rtx base;
- register int start, end;
- /* If X is a register, dependencies on its contents
- are recorded through the qty number mechanism.
- Just change the qty number of the register,
- mark it as invalid for expressions that refer to it,
- and remove it itself. */
- if (GET_CODE (x) == REG)
- {
- register int hash = HASH (x);
- reg_invalidate (REGNO (x));
- remove (lookup (x, hash), hash);
- return;
- }
- /* X is not a register; it must be a memory reference with
- a nonvarying address. Remove all hash table elements
- that refer to overlapping pieces of memory. */
- if (GET_CODE (x) != MEM)
- abort ();
- base = XEXP (x, 0);
- start = 0;
- if (GET_CODE (base) == CONST)
- base = XEXP (base, 0);
- if (GET_CODE (base) == PLUS
- && GET_CODE (XEXP (base, 1)) == CONST_INT)
- {
- start = INTVAL (XEXP (base, 1));
- base = XEXP (base, 0);
- }
- end = start + GET_MODE_SIZE (GET_MODE (x));
- for (i = 0; i < NBUCKETS; i++)
- {
- register struct table_elt *next;
- for (p = table[i]; p; p = next)
- {
- next = p->next_same_hash;
- if (refers_to_mem_p (p->exp, base, start, end))
- remove (p, i);
- }
- }
- }
- /* Remove all expressions that refer to register REGNO,
- since they are already invalid, and we are about to
- mark that register valid again and don't want the old
- expressions to reappear as valid. */
- static void
- remove_invalid_refs (regno)
- int regno;
- {
- register int i;
- register struct table_elt *p, *next;
- register rtx x = reg_rtx[regno];
- for (i = 0; i < NBUCKETS; i++)
- for (p = table[i]; p; p = next)
- {
- next = p->next_same_hash;
- if (GET_CODE (p->exp) != REG && refers_to_p (p->exp, x))
- remove (p, i);
- }
- }
- /* Remove from the hash table all expressions that reference memory,
- or some of them as specified by *WRITES. */
- static void
- invalidate_memory (writes)
- struct write_data *writes;
- {
- register int i;
- register struct table_elt *p, *next;
- int all = writes->all;
- int nonscalar = writes->nonscalar;
- for (i = 0; i < NBUCKETS; i++)
- for (p = table[i]; p; p = next)
- {
- next = p->next_same_hash;
- if (p->in_memory
- && (all
- || (nonscalar && p->exp->in_struct)
- || rtx_addr_varies_p (p->exp)))
- remove (p, i);
- }
- }
- /* Return the value of the integer term in X, if one is apparent;
- otherwise return 0.
- We do not check extremely carefully for the presence of integer terms
- but rather consider only the cases that `insert' notices
- for the `related_value' field. */
- static int
- get_integer_term (x)
- rtx x;
- {
- if (GET_CODE (x) == CONST)
- x = XEXP (x, 0);
- if (GET_CODE (x) == MINUS
- && GET_CODE (XEXP (x, 1)) == CONST_INT)
- return - INTVAL (XEXP (x, 1));
- if (GET_CODE (x) != PLUS)
- return 0;
- if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- return INTVAL (XEXP (x, 0));
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- return INTVAL (XEXP (x, 1));
- return 0;
- }
- static rtx
- get_related_value (x)
- rtx x;
- {
- if (GET_CODE (x) != CONST)
- return 0;
- x = XEXP (x, 0);
- if (GET_CODE (x) == PLUS)
- {
- if (GET_CODE (XEXP (x, 0)) == CONST_INT)
- return XEXP (x, 1);
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- return XEXP (x, 0);
- }
- else if (GET_CODE (x) == MINUS
- && GET_CODE (XEXP (x, 1)) == CONST_INT)
- return XEXP (x, 0);
- return 0;
- }
- /* Given an expression X of type CONST,
- and ELT which is its table entry (or 0 if it
- is not in the hash table),
- return an alternate expression for X as a register plus integer.
- If none can be found or it would not be a valid address, return 0. */
- static rtx
- use_related_value (x, elt)
- rtx x;
- struct table_elt *elt;
- {
- register struct table_elt *relt = 0;
- register struct table_elt *p;
- int offset;
- rtx addr;
- /* First, is there anything related known?
- If we have a table element, we can tell from that.
- Otherwise, must look it up. */
- if (elt != 0 && elt->related_value != 0)
- relt = elt;
- else if (elt == 0 && GET_CODE (x) == CONST)
- {
- rtx subexp = get_related_value (x);
- if (subexp != 0)
- relt = lookup (subexp, safe_hash (subexp) % NBUCKETS);
- }
- if (relt == 0)
- return 0;
- /* Search all related table entries for one that has an
- equivalent register. */
- p = relt;
- while (1)
- {
- if (p->first_same_value != 0
- && GET_CODE (p->first_same_value->exp) == REG)
- break;
- p = p->related_value;
- /* We went all the way around, so there is nothing to be found.
- Return failure. */
- if (p == relt)
- return 0;
- }
- offset = (get_integer_term (x) - get_integer_term (p->exp));
- if (offset == 0)
- abort ();
- addr = plus_constant (p->first_same_value->exp, offset);
- GO_IF_LEGITIMATE_ADDRESS (QImode, addr, win1);
- return 0;
- win1:
- return addr;
- }
- /* Hash an rtx. We are careful to make sure the value is never negative.
- Equivalent registers hash identically.
- Store 1 in do_not_record if any subexpression is volatile.
- Store 1 in hash_arg_in_memory if there is a use of MEM
- anywhere within X.
- Note that cse_insn knows that the hash code of a MEM expression
- is just (int) MEM plus the hash code of the address.
- It also knows it can use HASHREG to get the hash code of (REG n). */
- #define HASHBITS 16
- #define HASHREG(RTX) \
- ((((int) REG << 7) + reg_qty[REGNO (RTX)]) % NBUCKETS)
- static int
- canon_hash (x)
- rtx x;
- {
- register int i;
- register int hash = 0;
- register RTX_CODE code;
- register char *fmt;
- /* repeat is used to turn tail-recursion into iteration. */
- repeat:
- code = GET_CODE (x);
- switch (code)
- {
- case REG:
- {
- /* We do not invalidate anything on pushing or popping
- because they cannot change anything but the stack pointer;
- but that means we must consider the stack pointer volatile
- since it can be changed "mysteriously".
- We consider the function value register volatile
- because it can be referred to in multi-word modes.
- If it were live across basic block boundaries, that
- could cause trouble in register allocation.
- The only way this can happen is if it were substituted
- as a cse. This way we prevent that. */
- register int regno = REGNO (x);
- if (regno == STACK_POINTER_REGNUM
- || regno == FUNCTION_VALUE_REGNUM)
- {
- do_not_record = 1;
- return 0;
- }
- return hash + ((int) REG << 7) + reg_qty[regno];
- }
- /* Assume there is only one rtx object for any given label. */
- case LABEL_REF:
- return hash + ((int) LABEL_REF << 7) + (int) XEXP (x, 0);
- case SYMBOL_REF:
- return hash + ((int) SYMBOL_REF << 7) + (int) XEXP (x, 0);
- case MEM:
- hash_arg_in_memory = 1;
- /* Now that we have already found this special case,
- might as well speed it up as much as possible. */
- hash += (int) MEM;
- x = XEXP (x, 0);
- goto repeat;
- case VOLATILE:
- do_not_record = 1;
- return 0;
- case PRE_DEC:
- case PRE_INC:
- case POST_DEC:
- case POST_INC:
- case PC:
- case CC0:
- do_not_record = 1;
- return 0;
- }
- i = GET_RTX_LENGTH (code) - 1;
- hash += (int) code + (int) GET_MODE (x);
- fmt = GET_RTX_FORMAT (code);
- for (; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- /* If we are about to do the last recursive call
- needed at this level, change it into iteration.
- This function is called enough to be worth it. */
- if (i == 0)
- {
- x = XEXP (x, 0);
- goto repeat;
- }
- hash += canon_hash (XEXP (x, i));
- }
- else
- {
- register int tem = XINT (x, i);
- hash += ((1 << HASHBITS) - 1) & (tem + tem >> HASHBITS);
- }
- }
- return hash;
- }
- /* Like canon_hash but with no side effects. */
- static int
- safe_hash (x)
- rtx x;
- {
- int save_do_not_record = do_not_record;
- int save_hash_arg_in_memory = hash_arg_in_memory;
- int hash = canon_hash (x);
- hash_arg_in_memory = save_hash_arg_in_memory;
- do_not_record = save_do_not_record;
- return hash;
- }
- /* Return 1 iff X and Y would canonicalize into the same thing,
- without actually constructing the canonicalization of either one.
- If VALIDATE is nonzero,
- we assume X is an expression being processed from the rtl
- and Y was found in the hash table. We check register refs
- in Y for being marked as valid. */
- static int
- exp_equiv_p (x, y, validate)
- rtx x, y;
- int validate;
- {
- register int i;
- register int hash = 0;
- register RTX_CODE code = GET_CODE (x);
- register char *fmt;
- /* An expression is usually equivalent to itself,
- but not if it's a register that's invalid. */
- if (x == y)
- return (code != REG
- || !validate
- || reg_in_table[REGNO (y)] == reg_tick[REGNO (y)]);
- if (code != GET_CODE (y))
- return 0;
- if (code == REG)
- return (reg_qty[REGNO (x)] == reg_qty[REGNO (y)]
- && (!validate
- || reg_in_table[REGNO (y)] == reg_tick[REGNO (y)]));
- /* Assume there is only one rtx object to refer
- to any given label.
- We already know that X and Y are not the same object
- so they must differ. */
- if (code == LABEL_REF || code == SYMBOL_REF)
- return XEXP (x, 0) == XEXP (y, 0);
- /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent. */
- if (GET_MODE (x) != GET_MODE (y))
- return 0;
- /* Compare the elements. If any pair of corresponding elements
- fail to match, return 0 for the whole things. */
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'e')
- {
- if (exp_equiv_p (XEXP (x, i), XEXP (y, i), validate) == 0)
- return 0;
- }
- else
- {
- if (XINT (x, i) != XINT (y, i))
- return 0;
- }
- }
- return 1;
- }
- /* Return 1 iff any subexpression of X matches Y.
- Here we do not require that X or Y be valid (for registers referred to)
- for being in the hash table. */
- int
- refers_to_p (x, y)
- rtx x, y;
- {
- register int i;
- register RTX_CODE code;
- register char *fmt;
- repeat:
- if (x == y)
- return 1;
- code = GET_CODE (x);
- /* If X as a whole has the same code as Y, they may match.
- If so, return 1. */
- if (code == GET_CODE (y))
- {
- if (exp_equiv_p (x, y, 0))
- return 1;
- }
- /* X does not match, so try its subexpressions. */
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- if (i == 0)
- {
- x = XEXP (x, 0);
- goto repeat;
- }
- else
- if (refers_to_p (XEXP (x, i), y))
- return 1;
- return 0;
- }
- /* Return 1 iff any subexpression of X refers to memory
- at an address of REG plus some offset
- such that any of the bytes' offsets fall between START (inclusive)
- and END (exclusive).
- The value is undefined if X is a varying address.
- This function is not used in such cases. */
- int
- refers_to_mem_p (x, reg, start, end)
- rtx x, reg;
- int start, end;
- {
- register int i;
- register RTX_CODE code;
- register char *fmt;
- repeat:
- code = GET_CODE (x);
- if (code == MEM)
- {
- register rtx addr = XEXP (x, 0); /* Get the address. */
- int myend;
- if (GET_CODE (addr) == CONST)
- addr = XEXP (addr, 0);
- if (addr == reg)
- i = 0;
- else if (GET_CODE (addr) == PLUS
- && XEXP (addr, 0) == reg
- && GET_CODE (XEXP (addr, 1)) == CONST_INT)
- i = INTVAL (XEXP (addr, 1));
- else
- return 0;
- myend = i + GET_MODE_SIZE (GET_MODE (x));
- return myend > start && i < end;
- }
- /* X does not match, so try its subexpressions. */
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- if (i == 0)
- {
- x = XEXP (x, 0);
- goto repeat;
- }
- else
- if (refers_to_mem_p (XEXP (x, i), reg, start, end))
- return 1;
- return 0;
- }
- /* Canonicalize an expression:
- replace each register reference inside it
- with the "oldest" equivalent register. */
- static rtx
- canon_reg (x)
- rtx x;
- {
- register int i;
- register RTX_CODE code = GET_CODE (x);
- register char *fmt;
- if (code == REG)
- {
- register int qty = reg_qty[REGNO (x)];
- register rtx new = reg_rtx[qty_first_reg[qty]];
- return new ? new : x;
- }
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- {
- if (fmt[i] == 'E')
- abort ();
- if (fmt[i] == 'e')
- XEXP (x, i) = canon_reg (XEXP (x, i));
- }
- return x;
- }
- /* If X is a nontrivial arithmetic operation on an argument
- for which a constant value can be determined, return
- the result of operating on that value, as a constant.
- Otherwise, return X, possibly with one or more operands
- modified by recursive calls to this function. */
- static rtx
- fold_rtx (x)
- rtx x;
- {
- register RTX_CODE code = GET_CODE (x);
- register char *fmt;
- register int i, val;
- rtx const_arg[2];
- const_arg[0] = 0;
- const_arg[1] = 0;
- /* Try folding our operands.
- Then see which ones have constant values known. */
- fmt = GET_RTX_FORMAT (code);
- for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
- if (fmt[i] == 'e')
- {
- register rtx tem = fold_rtx (XEXP (x, i));
- XEXP (x, i) = tem;
- if (i < 2)
- {
- if (GET_CODE (tem) == CONST_INT)
- const_arg[i] = tem;
- else if (GET_CODE (tem) == REG
- && qty_const[reg_qty[REGNO (tem)]] != 0)
- const_arg[i] = qty_const[reg_qty[REGNO (tem)]];
- }
- }
- /* Now decode the kind of rtx X is
- and either return X (if nothing can be done)
- or store a value in VAL and drop through
- (to return a CONST_INT for the integer VAL). */
- if (GET_RTX_LENGTH (code) == 1)
- {
- register int arg0;
- if (const_arg[0] == 0)
- {
- return x;
- }
- arg0 = INTVAL (const_arg[0]);
- switch (GET_CODE (x))
- {
- case NOT:
- val = ~ arg0;
- break;
- case NEG:
- val = - arg0;
- break;
- case SIGN_EXTEND:
- val = arg0;
- break;
- default:
- return x;
- }
- }
- else if (GET_RTX_LENGTH (code) == 2)
- {
- register int arg0, arg1;
- /* If 1st arg is the condition codes, 2nd must be zero
- and this must be a comparison.
- Decode the info on how the previous insn set the cc0
- and use that to deduce result of comparison. */
- if (XEXP (x, 0) == cc0_rtx)
- {
- if (prev_insn_cc0 == 0
- || const_arg[1] != const0_rtx)
- return x;
- if (code == LEU || code == LTU || code == GEU || code == GTU)
- arg0 = prev_insn_cc0 & 7;
- else
- arg0 = (prev_insn_cc0 >> 3) & 7;
- if (arg0 == 7) arg0 = -1;
- switch (code)
- {
- case LE:
- case LEU:
- return (arg0 <= 0) ? const1_rtx : const0_rtx;
- case LT:
- case LTU:
- return (arg0 < 0) ? const1_rtx : const0_rtx;
- case GE:
- case GEU:
- return (arg0 >= 0) ? const1_rtx : const0_rtx;
- case GT:
- case GTU:
- return (arg0 > 0) ? const1_rtx : const0_rtx;
- case NE:
- return (arg0 != 0) ? const1_rtx : const0_rtx;
- case EQ:
- return (arg0 == 0) ? const1_rtx : const0_rtx;
- default:
- abort ();
- }
- }
- if (const_arg[0] == 0 || const_arg[1] == 0)
- {
- /* Even if we can't compute a constant result,
- there are some cases worth simplifying. */
- if (code == PLUS)
- {
- if (const_arg[0] != 0 && INTVAL (const_arg[0]) == 0)
- return XEXP (x, 1);
- if (const_arg[1] != 0 && INTVAL (const_arg[1]) == 0)
- return XEXP (x, 0);
- if (const_arg[0] != 0 && GET_CODE (XEXP (x, 1)) == PLUS
- && (CONSTANT_ADDRESS_P (XEXP (XEXP (x, 1), 0))
- || CONSTANT_ADDRESS_P (XEXP (XEXP (x, 1), 1))))
- /* constant + (variable + constant)
- can result if an index register is made constant.
- We simplify this by adding the constants.
- If we did not, it would become an invalid address. */
- return plus_constant (XEXP (x, 1),
- INTVAL (const_arg[0]));
- if (const_arg[1] != 0 && GET_CODE (XEXP (x, 0)) == PLUS
- && (CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 0))
- || CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1))))
- return plus_constant (XEXP (x, 0),
- INTVAL (const_arg[1]));
- }
- if (code == MINUS)
- {
- if (const_arg[1] != 0 && INTVAL (const_arg[1]) == 0)
- return XEXP (x, 0);
- }
- /* PLUS and MULT can appear inside of a MEM.
- In such situations, a constant term must come second. */
- if (code == MULT || code == PLUS)
- if (const_arg[0] != 0)
- {
- XEXP (x, 0) = XEXP (x, 1);
- XEXP (x, 1) = const_arg[0];
- }
- return x;
- }
- arg0 = INTVAL (const_arg[0]);
- arg1 = INTVAL (const_arg[1]);
- switch (code)
- {
- case PLUS:
- val = arg0 + arg1;
- break;
- case MINUS:
- if (GET_MODE (x) == VOIDmode)
- /* Overflowless comparison:
- cannot represent an exact answer, so don't fold.
- This is used only to set the CC0,
- and fold_cc0 will take care of it. */
- return x;
- val = arg0 - arg1;
- break;
- case MULT:
- val = arg0 * arg1;
- break;
- case DIV:
- val = arg0 / arg1;
- break;
- case MOD:
- val = arg0 % arg1;
- break;
- case UMULT:
- val = (unsigned) arg0 * arg1;
- break;
- case UDIV:
- val = (unsigned) arg0 / arg1;
- break;
- case UMOD:
- val = (unsigned) arg0 % arg1;
- break;
- case AND:
- val = arg0 & arg1;
- break;
- case IOR:
- val = arg0 | arg1;
- break;
- case XOR:
- val = arg0 ^ arg1;
- break;
- case NE:
- val = arg0 != arg1;
- break;
- case EQ:
- val = arg0 == arg1;
- break;
- case LE:
- val = arg0 <= arg1;
- break;
- case LT:
- val = arg0 < arg1;
- break;
- case GE:
- val = arg0 >= arg1;
- break;
- case GT:
- val = arg0 > arg1;
- break;
- case LEU:
- val = ((unsigned) arg0) <= ((unsigned) arg1);
- break;
- case LTU:
- val = ((unsigned) arg0) < ((unsigned) arg1);
- break;
- case GEU:
- val = ((unsigned) arg0) >= ((unsigned) arg1);
- break;
- case GTU:
- val = ((unsigned) arg0) > ((unsigned) arg1);
- break;
- case LSHIFT:
- val = ((unsigned) arg0) << arg1;
- break;
- case ASHIFT:
- val = arg0 << arg1;
- break;
- case ROTATERT:
- arg1 = - arg1;
- case ROTATE:
- {
- int size = GET_MODE_SIZE (GET_MODE (x)) * BITS_PER_UNIT;
- if (arg1 > 0)
- {
- arg1 %= size;
- val = ((((unsigned) arg0) << arg1)
- | (((unsigned) arg0) >> (size - arg1)));
- }
- else if (arg1 < 0)
- {
- arg1 = (- arg1) % size;
- val = ((((unsigned) arg0) >> arg1)
- | (((unsigned) arg0) << (size - arg1)));
- }
- else
- val = arg0;
- }
- break;
- case LSHIFTRT:
- val = ((unsigned) arg0) >> arg1;
- break;
- case ASHIFTRT:
- val = arg0 >> arg1;
- break;
- default:
- return x;
- }
- }
- else if (code == IF_THEN_ELSE && const_arg[0] != 0)
- return XEXP (x, ((INTVAL (const_arg[0]) != 0) ? 1 : 2));
- else
- return x;
- /* ??? Here must clear or set the bits that don't belong in our mode. */
- return gen_rtx (CONST_INT, VOIDmode, val);
- }
- /* Given an expression X which is used to set CC0,
- return an integer recording (in the encoding used for prev_insn_cc0)
- how the condition codes would be set by that expression.
- Return 0 if the value is not constant. */
- static int
- fold_cc0 (x)
- rtx x;
- {
- if (GET_CODE (x) == MINUS && GET_MODE (x) == VOIDmode)
- {
- rtx y0 = fold_rtx (XEXP (x, 0));
- rtx y1 = fold_rtx (XEXP (x, 1));
- int i0, i1;
- if (GET_CODE (y0) != CONST_INT || GET_CODE (y1) != CONST_INT)
- return 0;
- i0 = INTVAL (y0);
- i1 = INTVAL (y1);
- return 100 + ((i0 < i1 ? 7 : i0 > i1) << 3)
- + (((unsigned) i0 < (unsigned) i1) ? 7
- : ((unsigned) i0 > (unsigned) i1));
- }
- x = fold_rtx (x);
- if (GET_CODE (x) != CONST_INT)
- return 0;
- return 100 + ((INTVAL (x) < 0 ? 7 : INTVAL (x) > 0) << 3) + INTVAL (x) != 0;
- }
- /* Attempt to prove that a loop will be executed >= 1 times,
- or prove it will be executed 0 times.
- If either can be proved, delete some of the code. */
- predecide_loop_entry (insn)
- register rtx insn;
- {
- register rtx jump = NEXT_INSN (insn);
- register rtx p = JUMP_LABEL (jump);
- register rtx loop_top_label = NEXT_INSN (NEXT_INSN (jump));
- enum { UNK, DELETE_LOOP, DELETE_JUMP } disposition = UNK;
- /* Trace the flow of control through the end test,
- propagating constants, to see if result is determined. */
- prev_insn_cc0 = 0;
- while (1)
- {
- /* Arriving at end of loop means endtest will drop out. */
- if (GET_CODE (p) == NOTE
- && NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)
- {
- disposition = DELETE_LOOP;
- break;
- }
- else if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == NOTE)
- ;
- /* We only know how to handle two kinds of insns:
- conditional jumps, and those that set the condition codes. */
- else if (GET_CODE (p) == INSN && GET_CODE (PATTERN (p)) == SET
- && SET_DEST (PATTERN (p)) == cc0_rtx)
- {
- prev_insn_cc0 = fold_cc0 (copy_rtx (SET_SRC (PATTERN (p))));
- }
- else if (GET_CODE (p) == JUMP_INSN
- && GET_CODE (PATTERN (p)) == SET
- && SET_DEST (PATTERN (p)) == pc_rtx)
- {
- register rtx target
- = fold_rtx (copy_rtx (SET_SRC (PATTERN (p))));
- if (GET_CODE (target) == LABEL_REF)
- p = XEXP (target, 0);
- else if (target != pc_rtx)
- /* If destination of jump is not fixed, give up. */
- break;
- }
- /* Any other kind of insn means we don't know
- what result the test will have. */
- else
- break;
- /* Arriving at top of loop means we can drop straight in.
- Check here because we can arrive only via a jump insn
- which would have changed P above. */
- if (p == loop_top_label)
- {
- disposition = DELETE_JUMP;
- break;
- }
- /* We went past one insn; consider the next. */
- p = NEXT_INSN (p);
- }
- if (disposition == DELETE_JUMP)
- {
- /* We know the loop test will succeed the first time,
- so delete the jump to the test; drop right into loop.
- Note that one call to delete_insn gets the BARRIER as well. */
- delete_insn (jump);
- }
- if (disposition == DELETE_LOOP)
- {
- /* We know the endtest will fail and drop right out of the loop,
- but it isn't safe to delete the loop here.
- There could be jumps into it from outside.
- So make the entry-jump jump around the loop.
- This will cause find_basic_blocks to delete it if appropriate. */
- register rtx label = gen_label_rtx ();
- emit_label_after (label, p);
- redirect_jump (jump, label);
- }
- }
- /* CSE processing for one instruction.
- First simplify sources and addresses of all assignments
- in the instruction, using previously-computed equivalents values.
- Then install the new sources and destinations in the table
- of available values. */
- static rtx set[MAX_SETS_PER_INSN];
- static struct table_elt *src_elt[MAX_SETS_PER_INSN];
- static int src_hash_code[MAX_SETS_PER_INSN];
- static int dest_hash_code[MAX_SETS_PER_INSN];
- static char src_in_memory[MAX_SETS_PER_INSN];
- static char src_volatile[MAX_SETS_PER_INSN];
- static void
- cse_insn (insn)
- rtx insn;
- {
- register rtx x = PATTERN (insn);
- register int i;
- register int n_sets = 0;
- /* Records what this insn does to set CC0,
- using same encoding used for prev_insn_cc0. */
- int this_insn_cc0 = 0;
- struct write_data writes_memory;
- static struct write_data init = {0, 0, 0};
- writes_memory = init;
- /* Find all the SETs and CLOBBERs in this instruction.
- Record all the SETs in the array `set' and count them.
- Also determine whether there is a CLOBBER that invalidates
- all memory references, or all references at varying addresses. */
- if (GET_CODE (x) == SET)
- {
- n_sets = 1;
- set[0] = x;
- /* Return now for unconditional jumps.
- The never need cse processing, so this does not hurt.
- The reason is not efficiency but rather
- so that we can test at the end for instructions
- that have been simplified to unconditional jumps
- and not be misled by unchanged instructions
- that were unconditional jumps to begin with. */
- if (SET_DEST (x) == pc_rtx
- && GET_CODE (SET_SRC (x)) == LABEL_REF)
- return;
- }
- else if (GET_CODE (x) == PARALLEL)
- {
- register int lim;
- lim = XVECLEN (x, 0);
- for (i = 0; i < lim; i++)
- {
- register rtx y = XVECEXP (x, 0, i);
- if (GET_CODE (y) == SET)
- set[n_sets++] = y;
- else if (GET_CODE (y) == CLOBBER)
- note_mem_written (XEXP (y, 0), &writes_memory);
- else if (GET_CODE (y) == CALL)
- canon_reg (y);
- }
- }
- else if (GET_CODE (x) == CLOBBER)
- note_mem_written (XEXP (x, 0), &writes_memory);
- else if (GET_CODE (x) == CALL)
- canon_reg (x);
- if (n_sets == 0)
- {
- invalidate_from_clobbers (&writes_memory, x);
- return;
- }
- /* Canonicalize sources and addresses of destinations.
- set src_elt[i] to the class each source belongs to.
- Detect assignments from or to volatile things
- and set set[i] to zero so they will be ignored
- in the rest of this function.
- Nothing in this loop changes the hash table or the register chains. */
- for (i = 0; i < n_sets; i++)
- {
- register rtx src, dest, addr;
- register struct table_elt *elt;
- dest = SET_DEST (set[i]);
- src = SET_SRC (set[i]);
- /* Replace each registers in SRC with oldest equivalent register,
- but if DEST is a register do not replace it if it appears in SRC. */
- if (GET_CODE (dest) == REG)
- {
- int tem = reg_qty[REGNO (dest)];
- reg_qty[REGNO (dest)] = REGNO (dest);
- src = canon_reg (src);
- reg_qty[REGNO (dest)] = tem;
- }
- else
- src = canon_reg (src);
- /* Compute SRC's hash code, and also notice if it
- should not be recorded at all. In that case,
- prevent any further processing of this assignment. */
- do_not_record = 0;
- hash_arg_in_memory = 0;
- src = fold_rtx (src);
- /* If we have (NOT Y), see if Y is known to be (NOT Z).
- If so, (NOT Y) simplifies to Z. */
- if (GET_CODE (src) == NOT || GET_CODE (src) == NEG)
- {
- rtx y = lookup_as_function (XEXP (src, 0), GET_CODE (src));
- if (y != 0)
- src = y;
- }
- /* If storing a constant value in a register that
- previously held the constant value 0,
- record this fact with a REG_WAS_0 note on this insn. */
- if (GET_CODE (src) == CONST_INT
- && GET_CODE (dest) == REG
- && qty_const[reg_qty[REGNO (dest)]] == const0_rtx)
- REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_WAS_0,
- dest, REG_NOTES (insn));
- src_hash_code[i] = HASH (src);
- src_volatile[i] = do_not_record;
- if (GET_CODE (src) == REG)
- {
- src_in_memory[i] = 0;
- src_elt[i] = 0;
- }
- else if (!src_volatile[i])
- {
- /* Replace the source with its cheapest equivalent. */
- elt = lookup (src, src_hash_code[i]);
- if (elt && elt != elt->first_same_value)
- {
- elt = elt->first_same_value;
- /* Find the cheapest one that is still valid. */
- while (GET_CODE (elt->exp) != REG
- && !exp_equiv_p (elt->exp, elt->exp, 1))
- elt = elt->next_same_value;
- src = copy_rtx (elt->exp);
- hash_arg_in_memory = 0;
- src_hash_code[i] = HASH (src);
- }
- /* If ELT is a constant, is there a register
- linearly related to it? If so, replace it
- with the sum of that register plus an offset. */
- if (GET_CODE (src) == CONST && n_sets == 1)
- {
- rtx newsrc = use_related_value (src, elt);
- if (newsrc)
- {
- src = newsrc;
- hash_arg_in_memory = 0;
- src_hash_code[i] = HASH (src);
- /* The new expression for the SRC has the same value
- as the previous one; so if the previous one is in
- the hash table, put the new one in as equivalent. */
- if (elt != 0)
- elt = insert (src, elt->first_same_value, src_hash_code[i]);
- /* The reg this insn sets is no longer a "constant" reg
- because SRC now depends on a register that may not
- be invariant. */
- REG_NOTES (insn) = 0;
- }
- }
- src_elt[i] = elt;
- src_in_memory[i] = hash_arg_in_memory;
- }
- /* Either canon_reg or the copy_rtx may have changed this. */
- /* Note it is not safe to replace the sources if there
- is more than one set. We could get an insn
- [(set (reg) (reg)) (set (reg) (reg))], which is probably
- not in the machine description.
- This case we could handle by breaking into several insns.
- Cases of partial substituttion cannot win at all. */
- /* Also, if this insn is setting a "constant" register,
- we may not replace the value that is given to it. */
- if (n_sets == 1)
- if (REG_NOTES (insn) == 0
- || (enum reg_note) GET_MODE (REG_NOTES (insn)) != REG_CONST)
- SET_SRC (set[i]) = src;
- do_not_record = 0;
- /* If storing into memory, do cse on the memory address.
- Also compute the hash code of the destination now,
- before the effects of this instruction are recorded,
- since the register values used in the address computation
- are those before this instruction. */
- /* We can discard a VOLATILE around the destination of the set
- because we never coalesce, reorder or delete stores into memory. */
- if (GET_CODE (dest) == VOLATILE)
- SET_SRC (set[i]) = dest = XEXP (dest, 0);
- if (GET_CODE (dest) == MEM)
- {
- register rtx addr;
- register int hash;
- canon_reg (dest);
- addr = fold_rtx (XEXP (dest, 0));
- XEXP (dest, 0) = addr;
- /* Pushing or popping does not invalidate anything. */
- if ((GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == PRE_INC
- || GET_CODE (addr) == POST_DEC || GET_CODE (addr) == POST_INC)
- && GET_CODE (XEXP (addr, 0)) == REG
- && REGNO (XEXP (addr, 0)) == STACK_POINTER_REGNUM)
- ;
- else
- /* Otherwise, decide whether we invalidate
- everything in memory, or just things at non-fixed places.
- Writing a large aggregate must invalidate everything
- because we don't know how long it is. */
- note_mem_written (dest, &writes_memory);
- /* Do not consider addresses of local and argument slots.
- The MEM expressions for args and non-register local variables
- are made only once and inserted in many instructions,
- as well as being used to control symbol table output.
- It is not safe to clobber them. */
- if ((GET_CODE (addr) == PLUS
- && GET_CODE (XEXP (addr, 0)) == REG
- && GET_CODE (XEXP (addr, 1)) == CONST_INT
- && (hash = REGNO (XEXP (addr, 0)),
- hash == FRAME_POINTER_REGNUM || hash == ARG_POINTER_REGNUM))
- || (GET_CODE (addr) == REG
- && (hash = REGNO (addr),
- hash == FRAME_POINTER_REGNUM || hash == ARG_POINTER_REGNUM)))
- ;
- else
- {
- hash = HASH (addr);
- if (! do_not_record)
- {
- elt = lookup (addr, hash);
- dest_hash_code[i] = ((int) MEM + hash) % NBUCKETS;
- if (elt && elt != elt->first_same_value)
- {
- elt = elt->first_same_value;
- /* Find the cheapest one that is still valid. */
- while (GET_CODE (elt->exp) != REG
- && !exp_equiv_p (elt->exp, elt->exp, 1))
- elt = elt->next_same_value;
- XEXP (dest, 0) = addr
- = copy_rtx (elt->exp);
- }
- }
- }
- }
- /* For compound destinations that modify only a part of
- register or memory location, we cannot enter them
- in the hash table since we know only part of the value.
- Set src_volatile to prevent this.
- But we must invalidate the entire value.
- So prevent set[i] from becoming zero. */
- if (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == STRICT_LOW_PART
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT)
- src_volatile[i] = 1;
- /* No further processing for this assignment
- if destination is volatile. */
- else if (do_not_record
- || (GET_CODE (dest) == REG
- ? REGNO (dest) == STACK_POINTER_REGNUM
- : GET_CODE (dest) != MEM))
- set[i] = 0;
- if (dest == cc0_rtx && GET_CODE (src) == MINUS)
- this_insn_cc0 = fold_cc0 (src);
- }
- /* Now enter all non-volatile source expressions in the hash table
- if they are not already present.
- Record in src_elt the heads of their equivalence classes.
- This way we can insert the corresponding destinations into
- the same classes even if the actual sources are no longer in them
- (having been invalidated). */
- for (i = 0; i < n_sets; i++)
- if (set[i] && src_elt[i] == 0 && ! src_volatile[i])
- {
- register rtx src = SET_SRC (set[i]);
- register struct table_elt *elt;
- /* Note that these insert_regs calls cannot remove
- any of the src_elt's, because they would have failed to match
- if not still valid. */
- if (insert_regs (src, 0, 0))
- src_hash_code[i] = HASH (src);
- elt = insert (src, 0, src_hash_code[i]);
- elt->in_memory = src_in_memory[i];
- src_elt[i] = elt->first_same_value;
- }
- invalidate_from_clobbers (&writes_memory, x);
- /* Now invalidate everything set by this instruction.
- If a SUBREG or other funny destination is being set,
- set[i] is still nonzero, so here we invalidate the reg
- a part of which is being set. */
- for (i = 0; i < n_sets; i++)
- if (set[i])
- {
- register rtx dest = SET_DEST (set[i]);
- while (GET_CODE (dest) == SUBREG
- || GET_CODE (dest) == STRICT_LOW_PART
- || GET_CODE (dest) == ZERO_EXTRACT
- || GET_CODE (dest) == SIGN_EXTRACT)
- dest = XEXP (dest, 0);
- /* Needed for registers to remove the register from its
- previous quantity's chain.
- Needed for memory if this is a nonvarying address, unless
- we have just done an invalidate_memory that covers even those. */
- if (GET_CODE (dest) == REG
- || (! writes_memory.all && ! rtx_addr_varies_p (dest)))
- invalidate (dest);
- }
- /* We may have just removed some of the src_elt's.
- So replace each one with the current head of the same class. */
- for (i = 0; i < n_sets; i++)
- if (set[i] && ! src_volatile[i] && src_elt[i]->first_same_value == 0)
- {
- register struct table_elt *elt = src_elt[i];
- /* If elt was removed, find current head of same class,
- or 0 if nothing remains of that class. */
- while (elt && elt->first_same_value == 0)
- elt = elt->next_same_value;
- src_elt[i] = elt ? elt->first_same_value : 0;
- }
- /* Now insert the destinations into their equivalence classes.
- If the source is volatile, record the destination in
- a class of its own. */
- for (i = 0; i < n_sets; i++)
- if (set[i])
- {
- register rtx dest = SET_DEST (set[i]);
- register struct table_elt *elt = src_elt[i];
- if (src_volatile[i])
- elt = 0;
- if (insert_regs (dest, elt, 1))
- dest_hash_code[i] = HASHREG (dest);
- elt = insert (dest, elt, dest_hash_code[i]);
- elt->in_memory = GET_CODE (dest) == MEM;
- }
- /* Did this insn become an unconditional branch or become a no-op? */
- if (GET_CODE (insn) == JUMP_INSN
- && GET_CODE (x) == SET
- && SET_DEST (x) == pc_rtx)
- {
- if (SET_SRC (x) == pc_rtx)
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- cse_jumps_altered = 1;
- /* If previous insn just set CC0 for us, delete it too. */
- if (prev_insn_cc0 != 0)
- {
- PUT_CODE (prev_insn, NOTE);
- NOTE_LINE_NUMBER (prev_insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (prev_insn) = 0;
- }
- }
- else if (GET_CODE (SET_SRC (x)) == LABEL_REF)
- {
- emit_barrier_after (insn);
- cse_jumps_altered = 1;
- /* If previous insn just set CC0 for us, delete it too. */
- if (prev_insn_cc0 != 0)
- {
- PUT_CODE (prev_insn, NOTE);
- NOTE_LINE_NUMBER (prev_insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (prev_insn) = 0;
- }
- }
- }
- prev_insn_cc0 = this_insn_cc0;
- prev_insn = insn;
- }
- /* Store 1 in *WRITES_PTR for those categories of memory ref
- that must be invalidated when the expression WRITTEN is stored in.
- If WRITTEN is null, say everything must be invalidated. */
- static void
- note_mem_written (written, writes_ptr)
- rtx written;
- struct write_data *writes_ptr;
- {
- static struct write_data everything = {1, 1, 1};
- if (written == 0)
- *writes_ptr = everything;
- else if (GET_CODE (written) == MEM)
- {
- if (rtx_addr_varies_p (written))
- {
- /* A varying address that is a sum indicates an array element,
- and that's just as good as a structure element
- in implying that we need not invalidate scalar variables. */
- if (!(written->in_struct
- || GET_CODE (XEXP (written, 0)) == PLUS))
- writes_ptr->all = 1;
- writes_ptr->nonscalar = 1;
- }
- writes_ptr->var = 1;
- }
- }
- /* Perform invalidation on the basis of everything about an insn
- except for invalidating the actual places that are SET in it.
- This includes the places CLOBBERed, and anything that might
- alias with something that is SET or CLOBBERed.
- W points to the writes_memory for this insn, a struct write_data
- saying which kinds of memory references must be invalidated.
- X is the pattern of the insn. */
- static void
- invalidate_from_clobbers (w, x)
- struct write_data *w;
- rtx x;
- {
- /* If W->var is not set, W specifies no action.
- If W->all is set, this step gets all memory refs
- so they can be ignored in the rest of this function. */
- if (w->var)
- invalidate_memory (w);
- if (GET_CODE (x) == CLOBBER)
- {
- rtx ref = XEXP (x, 0);
- if (ref
- && (GET_CODE (ref) == REG
- || (GET_CODE (ref) == MEM && ! w->all)))
- invalidate (ref);
- }
- else if (GET_CODE (x) == PARALLEL)
- {
- register int i;
- for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
- {
- register rtx y = XVECEXP (x, 0, i);
- if (GET_CODE (y) == CLOBBER)
- {
- rtx ref = XEXP (y, 0);
- if (ref
- &&(GET_CODE (ref) == REG
- || (GET_CODE (ref) == MEM && !w->all)))
- invalidate (ref);
- }
- }
- }
- }
- static void cse_basic_block ();
- /* Perform cse on the instructions of a function.
- F is the first instruction.
- NREGS is one plus the highest pseudo-reg number used in the instruction.
- Returns 1 if jump_optimize should be redone due to simplifications
- in conditional jump instructions. */
- int
- cse_main (f, nregs)
- /* f is the first instruction of a chain of insns for one function */
- rtx f;
- /* nregs is the total number of registers used in it */
- int nregs;
- {
- register rtx insn = f;
- register int i;
- cse_jumps_altered = 0;
- init_recog ();
- max_reg = nregs;
- all_minus_one = (int *) alloca (nregs * sizeof (int));
- consec_ints = (int *) alloca (nregs * sizeof (int));
- for (i = 0; i < nregs; i++)
- {
- all_minus_one[i] = -1;
- consec_ints[i] = i;
- }
- reg_next_eqv = (int *) alloca (nregs * sizeof (int));
- reg_prev_eqv = (int *) alloca (nregs * sizeof (int));
- reg_qty = (int *) alloca (nregs * sizeof (int));
- reg_rtx = (rtx *) alloca (nregs * sizeof (rtx));
- reg_in_table = (int *) alloca (nregs * sizeof (int));
- reg_tick = (int *) alloca (nregs * sizeof (int));
- /* Discard all the free elements of the previous function
- since they are allocated in the temporarily obstack. */
- bzero (table, sizeof table);
- free_element_chain = 0;
- n_elements_made = 0;
- /* Loop over basic blocks */
- while (insn)
- {
- register rtx p = insn;
- register int i = 0;
- register int last_uid;
- /* Find end of next basic block */
- while (p && GET_CODE (p) != CODE_LABEL)
- {
- last_uid = INSN_UID (p);
- p = NEXT_INSN (p);
- i++;
- }
- cse_basic_block_end = last_uid;
- max_qty = max_reg + i * MAX_SETS_PER_INSN;
- cse_basic_block (insn, p);
- insn = p ? NEXT_INSN (p) : 0;
- }
- if (max_elements_made < n_elements_made)
- max_elements_made = n_elements_made;
- return cse_jumps_altered;
- }
- static void
- cse_basic_block (from, to)
- register rtx from, to;
- {
- register rtx insn;
- int *qv1 = (int *) alloca (max_qty * sizeof (int));
- int *qv2 = (int *) alloca (max_qty * sizeof (int));
- rtx *qv3 = (rtx *) alloca (max_qty * sizeof (rtx));
- qty_first_reg = qv1;
- qty_last_reg = qv2;
- qty_const = qv3;
- new_basic_block ();
- for (insn = from; insn != to; insn = NEXT_INSN (insn))
- {
- register RTX_CODE code = GET_CODE (insn);
- if (code == INSN || code == JUMP_INSN || code == CALL_INSN)
- cse_insn (insn);
- /* Memory, and some registers, are invalidate by subroutine calls. */
- if (code == CALL_INSN)
- {
- register int i;
- static struct write_data everything = {1, 1, 1};
- invalidate_memory (&everything);
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (call_clobbers_reg[i] && reg_rtx[i]
- && i != FRAME_POINTER_REGNUM
- && i != ARG_POINTER_REGNUM)
- invalidate (reg_rtx[i]);
- }
- /* Loop beginnings are often followed by jumps
- (that enter the loop above the endtest).
- See if we can prove the loop will be executed at least once;
- if so, delete the jump. Also perhaps we can prove loop
- will never be executed and delete the entire thing. */
- if (code == NOTE
- && NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG
- && GET_CODE (NEXT_INSN (insn)) == JUMP_INSN)
- {
- predecide_loop_entry (insn);
- /* Whether that jump was deleted or not,
- it certainly is the end of the basic block.
- Since the jump is unconditional,
- it requires no further processing here. */
- break;
- }
- }
- }
|