xref: /dflybsd-src/contrib/gcc-4.7/gcc/dse.c (revision 81fc95a5293ee307c688a350a3feb4734aaddbb4)
1e4b17023SJohn Marino /* RTL dead store elimination.
2e4b17023SJohn Marino    Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
3e4b17023SJohn Marino    Free Software Foundation, Inc.
4e4b17023SJohn Marino 
5e4b17023SJohn Marino    Contributed by Richard Sandiford <rsandifor@codesourcery.com>
6e4b17023SJohn Marino    and Kenneth Zadeck <zadeck@naturalbridge.com>
7e4b17023SJohn Marino 
8e4b17023SJohn Marino This file is part of GCC.
9e4b17023SJohn Marino 
10e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
11e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
12e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
13e4b17023SJohn Marino version.
14e4b17023SJohn Marino 
15e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
17e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18e4b17023SJohn Marino for more details.
19e4b17023SJohn Marino 
20e4b17023SJohn Marino You should have received a copy of the GNU General Public License
21e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
22e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
23e4b17023SJohn Marino 
24e4b17023SJohn Marino #undef BASELINE
25e4b17023SJohn Marino 
26e4b17023SJohn Marino #include "config.h"
27e4b17023SJohn Marino #include "system.h"
28e4b17023SJohn Marino #include "coretypes.h"
29e4b17023SJohn Marino #include "hashtab.h"
30e4b17023SJohn Marino #include "tm.h"
31e4b17023SJohn Marino #include "rtl.h"
32e4b17023SJohn Marino #include "tree.h"
33e4b17023SJohn Marino #include "tm_p.h"
34e4b17023SJohn Marino #include "regs.h"
35e4b17023SJohn Marino #include "hard-reg-set.h"
36e4b17023SJohn Marino #include "regset.h"
37e4b17023SJohn Marino #include "flags.h"
38e4b17023SJohn Marino #include "df.h"
39e4b17023SJohn Marino #include "cselib.h"
40e4b17023SJohn Marino #include "timevar.h"
41e4b17023SJohn Marino #include "tree-pass.h"
42e4b17023SJohn Marino #include "alloc-pool.h"
43e4b17023SJohn Marino #include "alias.h"
44e4b17023SJohn Marino #include "insn-config.h"
45e4b17023SJohn Marino #include "expr.h"
46e4b17023SJohn Marino #include "recog.h"
47e4b17023SJohn Marino #include "dse.h"
48e4b17023SJohn Marino #include "optabs.h"
49e4b17023SJohn Marino #include "dbgcnt.h"
50e4b17023SJohn Marino #include "target.h"
51e4b17023SJohn Marino #include "params.h"
52e4b17023SJohn Marino #include "tree-flow.h"
53e4b17023SJohn Marino 
54e4b17023SJohn Marino /* This file contains three techniques for performing Dead Store
55e4b17023SJohn Marino    Elimination (dse).
56e4b17023SJohn Marino 
57e4b17023SJohn Marino    * The first technique performs dse locally on any base address.  It
58e4b17023SJohn Marino    is based on the cselib which is a local value numbering technique.
59e4b17023SJohn Marino    This technique is local to a basic block but deals with a fairly
60e4b17023SJohn Marino    general addresses.
61e4b17023SJohn Marino 
62e4b17023SJohn Marino    * The second technique performs dse globally but is restricted to
63e4b17023SJohn Marino    base addresses that are either constant or are relative to the
64e4b17023SJohn Marino    frame_pointer.
65e4b17023SJohn Marino 
66e4b17023SJohn Marino    * The third technique, (which is only done after register allocation)
67e4b17023SJohn Marino    processes the spill spill slots.  This differs from the second
68e4b17023SJohn Marino    technique because it takes advantage of the fact that spilling is
69e4b17023SJohn Marino    completely free from the effects of aliasing.
70e4b17023SJohn Marino 
71e4b17023SJohn Marino    Logically, dse is a backwards dataflow problem.  A store can be
72e4b17023SJohn Marino    deleted if it if cannot be reached in the backward direction by any
73e4b17023SJohn Marino    use of the value being stored.  However, the local technique uses a
74e4b17023SJohn Marino    forwards scan of the basic block because cselib requires that the
75e4b17023SJohn Marino    block be processed in that order.
76e4b17023SJohn Marino 
77e4b17023SJohn Marino    The pass is logically broken into 7 steps:
78e4b17023SJohn Marino 
79e4b17023SJohn Marino    0) Initialization.
80e4b17023SJohn Marino 
81e4b17023SJohn Marino    1) The local algorithm, as well as scanning the insns for the two
82e4b17023SJohn Marino    global algorithms.
83e4b17023SJohn Marino 
84e4b17023SJohn Marino    2) Analysis to see if the global algs are necessary.  In the case
85e4b17023SJohn Marino    of stores base on a constant address, there must be at least two
86e4b17023SJohn Marino    stores to that address, to make it possible to delete some of the
87e4b17023SJohn Marino    stores.  In the case of stores off of the frame or spill related
88e4b17023SJohn Marino    stores, only one store to an address is necessary because those
89e4b17023SJohn Marino    stores die at the end of the function.
90e4b17023SJohn Marino 
91e4b17023SJohn Marino    3) Set up the global dataflow equations based on processing the
92e4b17023SJohn Marino    info parsed in the first step.
93e4b17023SJohn Marino 
94e4b17023SJohn Marino    4) Solve the dataflow equations.
95e4b17023SJohn Marino 
96e4b17023SJohn Marino    5) Delete the insns that the global analysis has indicated are
97e4b17023SJohn Marino    unnecessary.
98e4b17023SJohn Marino 
99e4b17023SJohn Marino    6) Delete insns that store the same value as preceeding store
100e4b17023SJohn Marino    where the earlier store couldn't be eliminated.
101e4b17023SJohn Marino 
102e4b17023SJohn Marino    7) Cleanup.
103e4b17023SJohn Marino 
104e4b17023SJohn Marino    This step uses cselib and canon_rtx to build the largest expression
105e4b17023SJohn Marino    possible for each address.  This pass is a forwards pass through
106e4b17023SJohn Marino    each basic block.  From the point of view of the global technique,
107e4b17023SJohn Marino    the first pass could examine a block in either direction.  The
108e4b17023SJohn Marino    forwards ordering is to accommodate cselib.
109e4b17023SJohn Marino 
110e4b17023SJohn Marino    We a simplifying assumption: addresses fall into four broad
111e4b17023SJohn Marino    categories:
112e4b17023SJohn Marino 
113e4b17023SJohn Marino    1) base has rtx_varies_p == false, offset is constant.
114e4b17023SJohn Marino    2) base has rtx_varies_p == false, offset variable.
115e4b17023SJohn Marino    3) base has rtx_varies_p == true, offset constant.
116e4b17023SJohn Marino    4) base has rtx_varies_p == true, offset variable.
117e4b17023SJohn Marino 
118e4b17023SJohn Marino    The local passes are able to process all 4 kinds of addresses.  The
119e4b17023SJohn Marino    global pass only handles (1).
120e4b17023SJohn Marino 
121e4b17023SJohn Marino    The global problem is formulated as follows:
122e4b17023SJohn Marino 
123e4b17023SJohn Marino      A store, S1, to address A, where A is not relative to the stack
124e4b17023SJohn Marino      frame, can be eliminated if all paths from S1 to the end of the
125e4b17023SJohn Marino      of the function contain another store to A before a read to A.
126e4b17023SJohn Marino 
127e4b17023SJohn Marino      If the address A is relative to the stack frame, a store S2 to A
128e4b17023SJohn Marino      can be eliminated if there are no paths from S1 that reach the
129e4b17023SJohn Marino      end of the function that read A before another store to A.  In
130e4b17023SJohn Marino      this case S2 can be deleted if there are paths to from S2 to the
131e4b17023SJohn Marino      end of the function that have no reads or writes to A.  This
132e4b17023SJohn Marino      second case allows stores to the stack frame to be deleted that
133e4b17023SJohn Marino      would otherwise die when the function returns.  This cannot be
134e4b17023SJohn Marino      done if stores_off_frame_dead_at_return is not true.  See the doc
135e4b17023SJohn Marino      for that variable for when this variable is false.
136e4b17023SJohn Marino 
137e4b17023SJohn Marino      The global problem is formulated as a backwards set union
138e4b17023SJohn Marino      dataflow problem where the stores are the gens and reads are the
139e4b17023SJohn Marino      kills.  Set union problems are rare and require some special
140e4b17023SJohn Marino      handling given our representation of bitmaps.  A straightforward
141e4b17023SJohn Marino      implementation of requires a lot of bitmaps filled with 1s.
142e4b17023SJohn Marino      These are expensive and cumbersome in our bitmap formulation so
143e4b17023SJohn Marino      care has been taken to avoid large vectors filled with 1s.  See
144e4b17023SJohn Marino      the comments in bb_info and in the dataflow confluence functions
145e4b17023SJohn Marino      for details.
146e4b17023SJohn Marino 
147e4b17023SJohn Marino    There are two places for further enhancements to this algorithm:
148e4b17023SJohn Marino 
149e4b17023SJohn Marino    1) The original dse which was embedded in a pass called flow also
150e4b17023SJohn Marino    did local address forwarding.  For example in
151e4b17023SJohn Marino 
152e4b17023SJohn Marino    A <- r100
153e4b17023SJohn Marino    ... <- A
154e4b17023SJohn Marino 
155e4b17023SJohn Marino    flow would replace the right hand side of the second insn with a
156e4b17023SJohn Marino    reference to r100.  Most of the information is available to add this
157e4b17023SJohn Marino    to this pass.  It has not done it because it is a lot of work in
158e4b17023SJohn Marino    the case that either r100 is assigned to between the first and
159e4b17023SJohn Marino    second insn and/or the second insn is a load of part of the value
160e4b17023SJohn Marino    stored by the first insn.
161e4b17023SJohn Marino 
162e4b17023SJohn Marino    insn 5 in gcc.c-torture/compile/990203-1.c simple case.
163e4b17023SJohn Marino    insn 15 in gcc.c-torture/execute/20001017-2.c simple case.
164e4b17023SJohn Marino    insn 25 in gcc.c-torture/execute/20001026-1.c simple case.
165e4b17023SJohn Marino    insn 44 in gcc.c-torture/execute/20010910-1.c simple case.
166e4b17023SJohn Marino 
167e4b17023SJohn Marino    2) The cleaning up of spill code is quite profitable.  It currently
168e4b17023SJohn Marino    depends on reading tea leaves and chicken entrails left by reload.
169e4b17023SJohn Marino    This pass depends on reload creating a singleton alias set for each
170e4b17023SJohn Marino    spill slot and telling the next dse pass which of these alias sets
171e4b17023SJohn Marino    are the singletons.  Rather than analyze the addresses of the
172e4b17023SJohn Marino    spills, dse's spill processing just does analysis of the loads and
173e4b17023SJohn Marino    stores that use those alias sets.  There are three cases where this
174e4b17023SJohn Marino    falls short:
175e4b17023SJohn Marino 
176e4b17023SJohn Marino      a) Reload sometimes creates the slot for one mode of access, and
177e4b17023SJohn Marino      then inserts loads and/or stores for a smaller mode.  In this
178e4b17023SJohn Marino      case, the current code just punts on the slot.  The proper thing
179e4b17023SJohn Marino      to do is to back out and use one bit vector position for each
180e4b17023SJohn Marino      byte of the entity associated with the slot.  This depends on
181e4b17023SJohn Marino      KNOWING that reload always generates the accesses for each of the
182e4b17023SJohn Marino      bytes in some canonical (read that easy to understand several
183e4b17023SJohn Marino      passes after reload happens) way.
184e4b17023SJohn Marino 
185e4b17023SJohn Marino      b) Reload sometimes decides that spill slot it allocated was not
186e4b17023SJohn Marino      large enough for the mode and goes back and allocates more slots
187e4b17023SJohn Marino      with the same mode and alias set.  The backout in this case is a
188e4b17023SJohn Marino      little more graceful than (a).  In this case the slot is unmarked
189e4b17023SJohn Marino      as being a spill slot and if final address comes out to be based
190e4b17023SJohn Marino      off the frame pointer, the global algorithm handles this slot.
191e4b17023SJohn Marino 
192e4b17023SJohn Marino      c) For any pass that may prespill, there is currently no
193e4b17023SJohn Marino      mechanism to tell the dse pass that the slot being used has the
194e4b17023SJohn Marino      special properties that reload uses.  It may be that all that is
195e4b17023SJohn Marino      required is to have those passes make the same calls that reload
196e4b17023SJohn Marino      does, assuming that the alias sets can be manipulated in the same
197e4b17023SJohn Marino      way.  */
198e4b17023SJohn Marino 
199e4b17023SJohn Marino /* There are limits to the size of constant offsets we model for the
200e4b17023SJohn Marino    global problem.  There are certainly test cases, that exceed this
201e4b17023SJohn Marino    limit, however, it is unlikely that there are important programs
202e4b17023SJohn Marino    that really have constant offsets this size.  */
203e4b17023SJohn Marino #define MAX_OFFSET (64 * 1024)
204e4b17023SJohn Marino 
205e4b17023SJohn Marino 
206e4b17023SJohn Marino static bitmap scratch = NULL;
207e4b17023SJohn Marino struct insn_info;
208e4b17023SJohn Marino 
209e4b17023SJohn Marino /* This structure holds information about a candidate store.  */
210e4b17023SJohn Marino struct store_info
211e4b17023SJohn Marino {
212e4b17023SJohn Marino 
213e4b17023SJohn Marino   /* False means this is a clobber.  */
214e4b17023SJohn Marino   bool is_set;
215e4b17023SJohn Marino 
216e4b17023SJohn Marino   /* False if a single HOST_WIDE_INT bitmap is used for positions_needed.  */
217e4b17023SJohn Marino   bool is_large;
218e4b17023SJohn Marino 
219e4b17023SJohn Marino   /* The id of the mem group of the base address.  If rtx_varies_p is
220e4b17023SJohn Marino      true, this is -1.  Otherwise, it is the index into the group
221e4b17023SJohn Marino      table.  */
222e4b17023SJohn Marino   int group_id;
223e4b17023SJohn Marino 
224e4b17023SJohn Marino   /* This is the cselib value.  */
225e4b17023SJohn Marino   cselib_val *cse_base;
226e4b17023SJohn Marino 
227e4b17023SJohn Marino   /* This canonized mem.  */
228e4b17023SJohn Marino   rtx mem;
229e4b17023SJohn Marino 
230e4b17023SJohn Marino   /* Canonized MEM address for use by canon_true_dependence.  */
231e4b17023SJohn Marino   rtx mem_addr;
232e4b17023SJohn Marino 
233e4b17023SJohn Marino   /* If this is non-zero, it is the alias set of a spill location.  */
234e4b17023SJohn Marino   alias_set_type alias_set;
235e4b17023SJohn Marino 
236e4b17023SJohn Marino   /* The offset of the first and byte before the last byte associated
237e4b17023SJohn Marino      with the operation.  */
238e4b17023SJohn Marino   HOST_WIDE_INT begin, end;
239e4b17023SJohn Marino 
240e4b17023SJohn Marino   union
241e4b17023SJohn Marino     {
242e4b17023SJohn Marino       /* A bitmask as wide as the number of bytes in the word that
243e4b17023SJohn Marino 	 contains a 1 if the byte may be needed.  The store is unused if
244e4b17023SJohn Marino 	 all of the bits are 0.  This is used if IS_LARGE is false.  */
245e4b17023SJohn Marino       unsigned HOST_WIDE_INT small_bitmask;
246e4b17023SJohn Marino 
247e4b17023SJohn Marino       struct
248e4b17023SJohn Marino 	{
249e4b17023SJohn Marino 	  /* A bitmap with one bit per byte.  Cleared bit means the position
250e4b17023SJohn Marino 	     is needed.  Used if IS_LARGE is false.  */
251e4b17023SJohn Marino 	  bitmap bmap;
252e4b17023SJohn Marino 
253e4b17023SJohn Marino 	  /* Number of set bits (i.e. unneeded bytes) in BITMAP.  If it is
254e4b17023SJohn Marino 	     equal to END - BEGIN, the whole store is unused.  */
255e4b17023SJohn Marino 	  int count;
256e4b17023SJohn Marino 	} large;
257e4b17023SJohn Marino     } positions_needed;
258e4b17023SJohn Marino 
259e4b17023SJohn Marino   /* The next store info for this insn.  */
260e4b17023SJohn Marino   struct store_info *next;
261e4b17023SJohn Marino 
262e4b17023SJohn Marino   /* The right hand side of the store.  This is used if there is a
263e4b17023SJohn Marino      subsequent reload of the mems address somewhere later in the
264e4b17023SJohn Marino      basic block.  */
265e4b17023SJohn Marino   rtx rhs;
266e4b17023SJohn Marino 
267e4b17023SJohn Marino   /* If rhs is or holds a constant, this contains that constant,
268e4b17023SJohn Marino      otherwise NULL.  */
269e4b17023SJohn Marino   rtx const_rhs;
270e4b17023SJohn Marino 
271e4b17023SJohn Marino   /* Set if this store stores the same constant value as REDUNDANT_REASON
272e4b17023SJohn Marino      insn stored.  These aren't eliminated early, because doing that
273e4b17023SJohn Marino      might prevent the earlier larger store to be eliminated.  */
274e4b17023SJohn Marino   struct insn_info *redundant_reason;
275e4b17023SJohn Marino };
276e4b17023SJohn Marino 
277e4b17023SJohn Marino /* Return a bitmask with the first N low bits set.  */
278e4b17023SJohn Marino 
279e4b17023SJohn Marino static unsigned HOST_WIDE_INT
lowpart_bitmask(int n)280e4b17023SJohn Marino lowpart_bitmask (int n)
281e4b17023SJohn Marino {
282e4b17023SJohn Marino   unsigned HOST_WIDE_INT mask = ~(unsigned HOST_WIDE_INT) 0;
283e4b17023SJohn Marino   return mask >> (HOST_BITS_PER_WIDE_INT - n);
284e4b17023SJohn Marino }
285e4b17023SJohn Marino 
286e4b17023SJohn Marino typedef struct store_info *store_info_t;
287e4b17023SJohn Marino static alloc_pool cse_store_info_pool;
288e4b17023SJohn Marino static alloc_pool rtx_store_info_pool;
289e4b17023SJohn Marino 
290e4b17023SJohn Marino /* This structure holds information about a load.  These are only
291e4b17023SJohn Marino    built for rtx bases.  */
292e4b17023SJohn Marino struct read_info
293e4b17023SJohn Marino {
294e4b17023SJohn Marino   /* The id of the mem group of the base address.  */
295e4b17023SJohn Marino   int group_id;
296e4b17023SJohn Marino 
297e4b17023SJohn Marino   /* If this is non-zero, it is the alias set of a spill location.  */
298e4b17023SJohn Marino   alias_set_type alias_set;
299e4b17023SJohn Marino 
300e4b17023SJohn Marino   /* The offset of the first and byte after the last byte associated
301e4b17023SJohn Marino      with the operation.  If begin == end == 0, the read did not have
302e4b17023SJohn Marino      a constant offset.  */
303e4b17023SJohn Marino   int begin, end;
304e4b17023SJohn Marino 
305e4b17023SJohn Marino   /* The mem being read.  */
306e4b17023SJohn Marino   rtx mem;
307e4b17023SJohn Marino 
308e4b17023SJohn Marino   /* The next read_info for this insn.  */
309e4b17023SJohn Marino   struct read_info *next;
310e4b17023SJohn Marino };
311e4b17023SJohn Marino typedef struct read_info *read_info_t;
312e4b17023SJohn Marino static alloc_pool read_info_pool;
313e4b17023SJohn Marino 
314e4b17023SJohn Marino 
315e4b17023SJohn Marino /* One of these records is created for each insn.  */
316e4b17023SJohn Marino 
317e4b17023SJohn Marino struct insn_info
318e4b17023SJohn Marino {
319e4b17023SJohn Marino   /* Set true if the insn contains a store but the insn itself cannot
320e4b17023SJohn Marino      be deleted.  This is set if the insn is a parallel and there is
321e4b17023SJohn Marino      more than one non dead output or if the insn is in some way
322e4b17023SJohn Marino      volatile.  */
323e4b17023SJohn Marino   bool cannot_delete;
324e4b17023SJohn Marino 
325e4b17023SJohn Marino   /* This field is only used by the global algorithm.  It is set true
326e4b17023SJohn Marino      if the insn contains any read of mem except for a (1).  This is
327e4b17023SJohn Marino      also set if the insn is a call or has a clobber mem.  If the insn
328e4b17023SJohn Marino      contains a wild read, the use_rec will be null.  */
329e4b17023SJohn Marino   bool wild_read;
330e4b17023SJohn Marino 
331e4b17023SJohn Marino   /* This is true only for CALL instructions which could potentially read
332e4b17023SJohn Marino      any non-frame memory location. This field is used by the global
333e4b17023SJohn Marino      algorithm.  */
334e4b17023SJohn Marino   bool non_frame_wild_read;
335e4b17023SJohn Marino 
336e4b17023SJohn Marino   /* This field is only used for the processing of const functions.
337e4b17023SJohn Marino      These functions cannot read memory, but they can read the stack
338e4b17023SJohn Marino      because that is where they may get their parms.  We need to be
339e4b17023SJohn Marino      this conservative because, like the store motion pass, we don't
340e4b17023SJohn Marino      consider CALL_INSN_FUNCTION_USAGE when processing call insns.
341e4b17023SJohn Marino      Moreover, we need to distinguish two cases:
342e4b17023SJohn Marino      1. Before reload (register elimination), the stores related to
343e4b17023SJohn Marino 	outgoing arguments are stack pointer based and thus deemed
344e4b17023SJohn Marino 	of non-constant base in this pass.  This requires special
345e4b17023SJohn Marino 	handling but also means that the frame pointer based stores
346e4b17023SJohn Marino 	need not be killed upon encountering a const function call.
347e4b17023SJohn Marino      2. After reload, the stores related to outgoing arguments can be
348e4b17023SJohn Marino 	either stack pointer or hard frame pointer based.  This means
349e4b17023SJohn Marino 	that we have no other choice than also killing all the frame
350e4b17023SJohn Marino 	pointer based stores upon encountering a const function call.
351e4b17023SJohn Marino      This field is set after reload for const function calls.  Having
352e4b17023SJohn Marino      this set is less severe than a wild read, it just means that all
353e4b17023SJohn Marino      the frame related stores are killed rather than all the stores.  */
354e4b17023SJohn Marino   bool frame_read;
355e4b17023SJohn Marino 
356e4b17023SJohn Marino   /* This field is only used for the processing of const functions.
357e4b17023SJohn Marino      It is set if the insn may contain a stack pointer based store.  */
358e4b17023SJohn Marino   bool stack_pointer_based;
359e4b17023SJohn Marino 
360e4b17023SJohn Marino   /* This is true if any of the sets within the store contains a
361e4b17023SJohn Marino      cselib base.  Such stores can only be deleted by the local
362e4b17023SJohn Marino      algorithm.  */
363e4b17023SJohn Marino   bool contains_cselib_groups;
364e4b17023SJohn Marino 
365e4b17023SJohn Marino   /* The insn. */
366e4b17023SJohn Marino   rtx insn;
367e4b17023SJohn Marino 
368e4b17023SJohn Marino   /* The list of mem sets or mem clobbers that are contained in this
369e4b17023SJohn Marino      insn.  If the insn is deletable, it contains only one mem set.
370e4b17023SJohn Marino      But it could also contain clobbers.  Insns that contain more than
371e4b17023SJohn Marino      one mem set are not deletable, but each of those mems are here in
372e4b17023SJohn Marino      order to provide info to delete other insns.  */
373e4b17023SJohn Marino   store_info_t store_rec;
374e4b17023SJohn Marino 
375e4b17023SJohn Marino   /* The linked list of mem uses in this insn.  Only the reads from
376e4b17023SJohn Marino      rtx bases are listed here.  The reads to cselib bases are
377e4b17023SJohn Marino      completely processed during the first scan and so are never
378e4b17023SJohn Marino      created.  */
379e4b17023SJohn Marino   read_info_t read_rec;
380e4b17023SJohn Marino 
381e4b17023SJohn Marino   /* The live fixed registers.  We assume only fixed registers can
382e4b17023SJohn Marino      cause trouble by being clobbered from an expanded pattern;
383e4b17023SJohn Marino      storing only the live fixed registers (rather than all registers)
384e4b17023SJohn Marino      means less memory needs to be allocated / copied for the individual
385e4b17023SJohn Marino      stores.  */
386e4b17023SJohn Marino   regset fixed_regs_live;
387e4b17023SJohn Marino 
388e4b17023SJohn Marino   /* The prev insn in the basic block.  */
389e4b17023SJohn Marino   struct insn_info * prev_insn;
390e4b17023SJohn Marino 
391e4b17023SJohn Marino   /* The linked list of insns that are in consideration for removal in
392e4b17023SJohn Marino      the forwards pass thru the basic block.  This pointer may be
393e4b17023SJohn Marino      trash as it is not cleared when a wild read occurs.  The only
394e4b17023SJohn Marino      time it is guaranteed to be correct is when the traversal starts
395e4b17023SJohn Marino      at active_local_stores.  */
396e4b17023SJohn Marino   struct insn_info * next_local_store;
397e4b17023SJohn Marino };
398e4b17023SJohn Marino 
399e4b17023SJohn Marino typedef struct insn_info *insn_info_t;
400e4b17023SJohn Marino static alloc_pool insn_info_pool;
401e4b17023SJohn Marino 
402e4b17023SJohn Marino /* The linked list of stores that are under consideration in this
403e4b17023SJohn Marino    basic block.  */
404e4b17023SJohn Marino static insn_info_t active_local_stores;
405e4b17023SJohn Marino static int active_local_stores_len;
406e4b17023SJohn Marino 
407e4b17023SJohn Marino struct bb_info
408e4b17023SJohn Marino {
409e4b17023SJohn Marino 
410e4b17023SJohn Marino   /* Pointer to the insn info for the last insn in the block.  These
411e4b17023SJohn Marino      are linked so this is how all of the insns are reached.  During
412e4b17023SJohn Marino      scanning this is the current insn being scanned.  */
413e4b17023SJohn Marino   insn_info_t last_insn;
414e4b17023SJohn Marino 
415e4b17023SJohn Marino   /* The info for the global dataflow problem.  */
416e4b17023SJohn Marino 
417e4b17023SJohn Marino 
418e4b17023SJohn Marino   /* This is set if the transfer function should and in the wild_read
419e4b17023SJohn Marino      bitmap before applying the kill and gen sets.  That vector knocks
420e4b17023SJohn Marino      out most of the bits in the bitmap and thus speeds up the
421e4b17023SJohn Marino      operations.  */
422e4b17023SJohn Marino   bool apply_wild_read;
423e4b17023SJohn Marino 
424e4b17023SJohn Marino   /* The following 4 bitvectors hold information about which positions
425e4b17023SJohn Marino      of which stores are live or dead.  They are indexed by
426e4b17023SJohn Marino      get_bitmap_index.  */
427e4b17023SJohn Marino 
428e4b17023SJohn Marino   /* The set of store positions that exist in this block before a wild read.  */
429e4b17023SJohn Marino   bitmap gen;
430e4b17023SJohn Marino 
431e4b17023SJohn Marino   /* The set of load positions that exist in this block above the
432e4b17023SJohn Marino      same position of a store.  */
433e4b17023SJohn Marino   bitmap kill;
434e4b17023SJohn Marino 
435e4b17023SJohn Marino   /* The set of stores that reach the top of the block without being
436e4b17023SJohn Marino      killed by a read.
437e4b17023SJohn Marino 
438e4b17023SJohn Marino      Do not represent the in if it is all ones.  Note that this is
439e4b17023SJohn Marino      what the bitvector should logically be initialized to for a set
440e4b17023SJohn Marino      intersection problem.  However, like the kill set, this is too
441e4b17023SJohn Marino      expensive.  So initially, the in set will only be created for the
442e4b17023SJohn Marino      exit block and any block that contains a wild read.  */
443e4b17023SJohn Marino   bitmap in;
444e4b17023SJohn Marino 
445e4b17023SJohn Marino   /* The set of stores that reach the bottom of the block from it's
446e4b17023SJohn Marino      successors.
447e4b17023SJohn Marino 
448e4b17023SJohn Marino      Do not represent the in if it is all ones.  Note that this is
449e4b17023SJohn Marino      what the bitvector should logically be initialized to for a set
450e4b17023SJohn Marino      intersection problem.  However, like the kill and in set, this is
451e4b17023SJohn Marino      too expensive.  So what is done is that the confluence operator
452e4b17023SJohn Marino      just initializes the vector from one of the out sets of the
453e4b17023SJohn Marino      successors of the block.  */
454e4b17023SJohn Marino   bitmap out;
455e4b17023SJohn Marino 
456e4b17023SJohn Marino   /* The following bitvector is indexed by the reg number.  It
457e4b17023SJohn Marino      contains the set of regs that are live at the current instruction
458e4b17023SJohn Marino      being processed.  While it contains info for all of the
459e4b17023SJohn Marino      registers, only the hard registers are actually examined.  It is used
460e4b17023SJohn Marino      to assure that shift and/or add sequences that are inserted do not
461e4b17023SJohn Marino      accidently clobber live hard regs.  */
462e4b17023SJohn Marino   bitmap regs_live;
463e4b17023SJohn Marino };
464e4b17023SJohn Marino 
465e4b17023SJohn Marino typedef struct bb_info *bb_info_t;
466e4b17023SJohn Marino static alloc_pool bb_info_pool;
467e4b17023SJohn Marino 
468e4b17023SJohn Marino /* Table to hold all bb_infos.  */
469e4b17023SJohn Marino static bb_info_t *bb_table;
470e4b17023SJohn Marino 
471e4b17023SJohn Marino /* There is a group_info for each rtx base that is used to reference
472e4b17023SJohn Marino    memory.  There are also not many of the rtx bases because they are
473e4b17023SJohn Marino    very limited in scope.  */
474e4b17023SJohn Marino 
475e4b17023SJohn Marino struct group_info
476e4b17023SJohn Marino {
477e4b17023SJohn Marino   /* The actual base of the address.  */
478e4b17023SJohn Marino   rtx rtx_base;
479e4b17023SJohn Marino 
480e4b17023SJohn Marino   /* The sequential id of the base.  This allows us to have a
481e4b17023SJohn Marino      canonical ordering of these that is not based on addresses.  */
482e4b17023SJohn Marino   int id;
483e4b17023SJohn Marino 
484e4b17023SJohn Marino   /* True if there are any positions that are to be processed
485e4b17023SJohn Marino      globally.  */
486e4b17023SJohn Marino   bool process_globally;
487e4b17023SJohn Marino 
488e4b17023SJohn Marino   /* True if the base of this group is either the frame_pointer or
489e4b17023SJohn Marino      hard_frame_pointer.  */
490e4b17023SJohn Marino   bool frame_related;
491e4b17023SJohn Marino 
492e4b17023SJohn Marino   /* A mem wrapped around the base pointer for the group in order to do
493e4b17023SJohn Marino      read dependency.  It must be given BLKmode in order to encompass all
494e4b17023SJohn Marino      the possible offsets from the base.  */
495e4b17023SJohn Marino   rtx base_mem;
496e4b17023SJohn Marino 
497e4b17023SJohn Marino   /* Canonized version of base_mem's address.  */
498e4b17023SJohn Marino   rtx canon_base_addr;
499e4b17023SJohn Marino 
500e4b17023SJohn Marino   /* These two sets of two bitmaps are used to keep track of how many
501e4b17023SJohn Marino      stores are actually referencing that position from this base.  We
502e4b17023SJohn Marino      only do this for rtx bases as this will be used to assign
503e4b17023SJohn Marino      positions in the bitmaps for the global problem.  Bit N is set in
504e4b17023SJohn Marino      store1 on the first store for offset N.  Bit N is set in store2
505e4b17023SJohn Marino      for the second store to offset N.  This is all we need since we
506e4b17023SJohn Marino      only care about offsets that have two or more stores for them.
507e4b17023SJohn Marino 
508e4b17023SJohn Marino      The "_n" suffix is for offsets less than 0 and the "_p" suffix is
509e4b17023SJohn Marino      for 0 and greater offsets.
510e4b17023SJohn Marino 
511e4b17023SJohn Marino      There is one special case here, for stores into the stack frame,
512e4b17023SJohn Marino      we will or store1 into store2 before deciding which stores look
513e4b17023SJohn Marino      at globally.  This is because stores to the stack frame that have
514e4b17023SJohn Marino      no other reads before the end of the function can also be
515e4b17023SJohn Marino      deleted.  */
516e4b17023SJohn Marino   bitmap store1_n, store1_p, store2_n, store2_p;
517e4b17023SJohn Marino 
518e4b17023SJohn Marino   /* These bitmaps keep track of offsets in this group escape this function.
519e4b17023SJohn Marino      An offset escapes if it corresponds to a named variable whose
520e4b17023SJohn Marino      addressable flag is set.  */
521e4b17023SJohn Marino   bitmap escaped_n, escaped_p;
522e4b17023SJohn Marino 
523e4b17023SJohn Marino   /* The positions in this bitmap have the same assignments as the in,
524e4b17023SJohn Marino      out, gen and kill bitmaps.  This bitmap is all zeros except for
525e4b17023SJohn Marino      the positions that are occupied by stores for this group.  */
526e4b17023SJohn Marino   bitmap group_kill;
527e4b17023SJohn Marino 
528e4b17023SJohn Marino   /* The offset_map is used to map the offsets from this base into
529e4b17023SJohn Marino      positions in the global bitmaps.  It is only created after all of
530e4b17023SJohn Marino      the all of stores have been scanned and we know which ones we
531e4b17023SJohn Marino      care about.  */
532e4b17023SJohn Marino   int *offset_map_n, *offset_map_p;
533e4b17023SJohn Marino   int offset_map_size_n, offset_map_size_p;
534e4b17023SJohn Marino };
535e4b17023SJohn Marino typedef struct group_info *group_info_t;
536e4b17023SJohn Marino typedef const struct group_info *const_group_info_t;
537e4b17023SJohn Marino static alloc_pool rtx_group_info_pool;
538e4b17023SJohn Marino 
539e4b17023SJohn Marino /* Tables of group_info structures, hashed by base value.  */
540e4b17023SJohn Marino static htab_t rtx_group_table;
541e4b17023SJohn Marino 
542e4b17023SJohn Marino /* Index into the rtx_group_vec.  */
543e4b17023SJohn Marino static int rtx_group_next_id;
544e4b17023SJohn Marino 
545e4b17023SJohn Marino DEF_VEC_P(group_info_t);
546e4b17023SJohn Marino DEF_VEC_ALLOC_P(group_info_t,heap);
547e4b17023SJohn Marino 
VEC(group_info_t,heap)548e4b17023SJohn Marino static VEC(group_info_t,heap) *rtx_group_vec;
549e4b17023SJohn Marino 
550e4b17023SJohn Marino 
551e4b17023SJohn Marino /* This structure holds the set of changes that are being deferred
552e4b17023SJohn Marino    when removing read operation.  See replace_read.  */
553e4b17023SJohn Marino struct deferred_change
554e4b17023SJohn Marino {
555e4b17023SJohn Marino 
556e4b17023SJohn Marino   /* The mem that is being replaced.  */
557e4b17023SJohn Marino   rtx *loc;
558e4b17023SJohn Marino 
559e4b17023SJohn Marino   /* The reg it is being replaced with.  */
560e4b17023SJohn Marino   rtx reg;
561e4b17023SJohn Marino 
562e4b17023SJohn Marino   struct deferred_change *next;
563e4b17023SJohn Marino };
564e4b17023SJohn Marino 
565e4b17023SJohn Marino typedef struct deferred_change *deferred_change_t;
566e4b17023SJohn Marino static alloc_pool deferred_change_pool;
567e4b17023SJohn Marino 
568e4b17023SJohn Marino static deferred_change_t deferred_change_list = NULL;
569e4b17023SJohn Marino 
570e4b17023SJohn Marino /* This are used to hold the alias sets of spill variables.  Since
571e4b17023SJohn Marino    these are never aliased and there may be a lot of them, it makes
572e4b17023SJohn Marino    sense to treat them specially.  This bitvector is only allocated in
573e4b17023SJohn Marino    calls from dse_record_singleton_alias_set which currently is only
574e4b17023SJohn Marino    made during reload1.  So when dse is called before reload this
575e4b17023SJohn Marino    mechanism does nothing.  */
576e4b17023SJohn Marino 
577e4b17023SJohn Marino static bitmap clear_alias_sets = NULL;
578e4b17023SJohn Marino 
579e4b17023SJohn Marino /* The set of clear_alias_sets that have been disqualified because
580e4b17023SJohn Marino    there are loads or stores using a different mode than the alias set
581e4b17023SJohn Marino    was registered with.  */
582e4b17023SJohn Marino static bitmap disqualified_clear_alias_sets = NULL;
583e4b17023SJohn Marino 
584e4b17023SJohn Marino /* The group that holds all of the clear_alias_sets.  */
585e4b17023SJohn Marino static group_info_t clear_alias_group;
586e4b17023SJohn Marino 
587e4b17023SJohn Marino /* The modes of the clear_alias_sets.  */
588e4b17023SJohn Marino static htab_t clear_alias_mode_table;
589e4b17023SJohn Marino 
590e4b17023SJohn Marino /* Hash table element to look up the mode for an alias set.  */
591e4b17023SJohn Marino struct clear_alias_mode_holder
592e4b17023SJohn Marino {
593e4b17023SJohn Marino   alias_set_type alias_set;
594e4b17023SJohn Marino   enum machine_mode mode;
595e4b17023SJohn Marino };
596e4b17023SJohn Marino 
597e4b17023SJohn Marino static alloc_pool clear_alias_mode_pool;
598e4b17023SJohn Marino 
599e4b17023SJohn Marino /* This is true except if cfun->stdarg -- i.e. we cannot do
600e4b17023SJohn Marino    this for vararg functions because they play games with the frame.  */
601e4b17023SJohn Marino static bool stores_off_frame_dead_at_return;
602e4b17023SJohn Marino 
603e4b17023SJohn Marino /* Counter for stats.  */
604e4b17023SJohn Marino static int globally_deleted;
605e4b17023SJohn Marino static int locally_deleted;
606e4b17023SJohn Marino static int spill_deleted;
607e4b17023SJohn Marino 
608e4b17023SJohn Marino static bitmap all_blocks;
609e4b17023SJohn Marino 
610e4b17023SJohn Marino /* Locations that are killed by calls in the global phase.  */
611e4b17023SJohn Marino static bitmap kill_on_calls;
612e4b17023SJohn Marino 
613e4b17023SJohn Marino /* The number of bits used in the global bitmaps.  */
614e4b17023SJohn Marino static unsigned int current_position;
615e4b17023SJohn Marino 
616e4b17023SJohn Marino 
617e4b17023SJohn Marino static bool gate_dse (void);
618e4b17023SJohn Marino static bool gate_dse1 (void);
619e4b17023SJohn Marino static bool gate_dse2 (void);
620e4b17023SJohn Marino 
621e4b17023SJohn Marino 
622e4b17023SJohn Marino /*----------------------------------------------------------------------------
623e4b17023SJohn Marino    Zeroth step.
624e4b17023SJohn Marino 
625e4b17023SJohn Marino    Initialization.
626e4b17023SJohn Marino ----------------------------------------------------------------------------*/
627e4b17023SJohn Marino 
628e4b17023SJohn Marino /* Hashtable callbacks for maintaining the "bases" field of
629e4b17023SJohn Marino    store_group_info, given that the addresses are function invariants.  */
630e4b17023SJohn Marino 
631e4b17023SJohn Marino static int
clear_alias_mode_eq(const void * p1,const void * p2)632e4b17023SJohn Marino clear_alias_mode_eq (const void *p1, const void *p2)
633e4b17023SJohn Marino {
634e4b17023SJohn Marino   const struct clear_alias_mode_holder * h1
635e4b17023SJohn Marino     = (const struct clear_alias_mode_holder *) p1;
636e4b17023SJohn Marino   const struct clear_alias_mode_holder * h2
637e4b17023SJohn Marino     = (const struct clear_alias_mode_holder *) p2;
638e4b17023SJohn Marino   return h1->alias_set == h2->alias_set;
639e4b17023SJohn Marino }
640e4b17023SJohn Marino 
641e4b17023SJohn Marino 
642e4b17023SJohn Marino static hashval_t
clear_alias_mode_hash(const void * p)643e4b17023SJohn Marino clear_alias_mode_hash (const void *p)
644e4b17023SJohn Marino {
645e4b17023SJohn Marino   const struct clear_alias_mode_holder *holder
646e4b17023SJohn Marino     = (const struct clear_alias_mode_holder *) p;
647e4b17023SJohn Marino   return holder->alias_set;
648e4b17023SJohn Marino }
649e4b17023SJohn Marino 
650e4b17023SJohn Marino 
651e4b17023SJohn Marino /* Find the entry associated with ALIAS_SET.  */
652e4b17023SJohn Marino 
653e4b17023SJohn Marino static struct clear_alias_mode_holder *
clear_alias_set_lookup(alias_set_type alias_set)654e4b17023SJohn Marino clear_alias_set_lookup (alias_set_type alias_set)
655e4b17023SJohn Marino {
656e4b17023SJohn Marino   struct clear_alias_mode_holder tmp_holder;
657e4b17023SJohn Marino   void **slot;
658e4b17023SJohn Marino 
659e4b17023SJohn Marino   tmp_holder.alias_set = alias_set;
660e4b17023SJohn Marino   slot = htab_find_slot (clear_alias_mode_table, &tmp_holder, NO_INSERT);
661e4b17023SJohn Marino   gcc_assert (*slot);
662e4b17023SJohn Marino 
663e4b17023SJohn Marino   return (struct clear_alias_mode_holder *) *slot;
664e4b17023SJohn Marino }
665e4b17023SJohn Marino 
666e4b17023SJohn Marino 
667e4b17023SJohn Marino /* Hashtable callbacks for maintaining the "bases" field of
668e4b17023SJohn Marino    store_group_info, given that the addresses are function invariants.  */
669e4b17023SJohn Marino 
670e4b17023SJohn Marino static int
invariant_group_base_eq(const void * p1,const void * p2)671e4b17023SJohn Marino invariant_group_base_eq (const void *p1, const void *p2)
672e4b17023SJohn Marino {
673e4b17023SJohn Marino   const_group_info_t gi1 = (const_group_info_t) p1;
674e4b17023SJohn Marino   const_group_info_t gi2 = (const_group_info_t) p2;
675e4b17023SJohn Marino   return rtx_equal_p (gi1->rtx_base, gi2->rtx_base);
676e4b17023SJohn Marino }
677e4b17023SJohn Marino 
678e4b17023SJohn Marino 
679e4b17023SJohn Marino static hashval_t
invariant_group_base_hash(const void * p)680e4b17023SJohn Marino invariant_group_base_hash (const void *p)
681e4b17023SJohn Marino {
682e4b17023SJohn Marino   const_group_info_t gi = (const_group_info_t) p;
683e4b17023SJohn Marino   int do_not_record;
684e4b17023SJohn Marino   return hash_rtx (gi->rtx_base, Pmode, &do_not_record, NULL, false);
685e4b17023SJohn Marino }
686e4b17023SJohn Marino 
687e4b17023SJohn Marino 
688e4b17023SJohn Marino /* Get the GROUP for BASE.  Add a new group if it is not there.  */
689e4b17023SJohn Marino 
690e4b17023SJohn Marino static group_info_t
get_group_info(rtx base)691e4b17023SJohn Marino get_group_info (rtx base)
692e4b17023SJohn Marino {
693e4b17023SJohn Marino   struct group_info tmp_gi;
694e4b17023SJohn Marino   group_info_t gi;
695e4b17023SJohn Marino   void **slot;
696e4b17023SJohn Marino 
697e4b17023SJohn Marino   if (base)
698e4b17023SJohn Marino     {
699e4b17023SJohn Marino       /* Find the store_base_info structure for BASE, creating a new one
700e4b17023SJohn Marino 	 if necessary.  */
701e4b17023SJohn Marino       tmp_gi.rtx_base = base;
702e4b17023SJohn Marino       slot = htab_find_slot (rtx_group_table, &tmp_gi, INSERT);
703e4b17023SJohn Marino       gi = (group_info_t) *slot;
704e4b17023SJohn Marino     }
705e4b17023SJohn Marino   else
706e4b17023SJohn Marino     {
707e4b17023SJohn Marino       if (!clear_alias_group)
708e4b17023SJohn Marino 	{
709e4b17023SJohn Marino 	  clear_alias_group = gi =
710e4b17023SJohn Marino 	    (group_info_t) pool_alloc (rtx_group_info_pool);
711e4b17023SJohn Marino 	  memset (gi, 0, sizeof (struct group_info));
712e4b17023SJohn Marino 	  gi->id = rtx_group_next_id++;
713e4b17023SJohn Marino 	  gi->store1_n = BITMAP_ALLOC (NULL);
714e4b17023SJohn Marino 	  gi->store1_p = BITMAP_ALLOC (NULL);
715e4b17023SJohn Marino 	  gi->store2_n = BITMAP_ALLOC (NULL);
716e4b17023SJohn Marino 	  gi->store2_p = BITMAP_ALLOC (NULL);
717e4b17023SJohn Marino 	  gi->escaped_p = BITMAP_ALLOC (NULL);
718e4b17023SJohn Marino 	  gi->escaped_n = BITMAP_ALLOC (NULL);
719e4b17023SJohn Marino 	  gi->group_kill = BITMAP_ALLOC (NULL);
720e4b17023SJohn Marino 	  gi->process_globally = false;
721e4b17023SJohn Marino 	  gi->offset_map_size_n = 0;
722e4b17023SJohn Marino 	  gi->offset_map_size_p = 0;
723e4b17023SJohn Marino 	  gi->offset_map_n = NULL;
724e4b17023SJohn Marino 	  gi->offset_map_p = NULL;
725e4b17023SJohn Marino 	  VEC_safe_push (group_info_t, heap, rtx_group_vec, gi);
726e4b17023SJohn Marino 	}
727e4b17023SJohn Marino       return clear_alias_group;
728e4b17023SJohn Marino     }
729e4b17023SJohn Marino 
730e4b17023SJohn Marino   if (gi == NULL)
731e4b17023SJohn Marino     {
732e4b17023SJohn Marino       *slot = gi = (group_info_t) pool_alloc (rtx_group_info_pool);
733e4b17023SJohn Marino       gi->rtx_base = base;
734e4b17023SJohn Marino       gi->id = rtx_group_next_id++;
735e4b17023SJohn Marino       gi->base_mem = gen_rtx_MEM (BLKmode, base);
736e4b17023SJohn Marino       gi->canon_base_addr = canon_rtx (base);
737e4b17023SJohn Marino       gi->store1_n = BITMAP_ALLOC (NULL);
738e4b17023SJohn Marino       gi->store1_p = BITMAP_ALLOC (NULL);
739e4b17023SJohn Marino       gi->store2_n = BITMAP_ALLOC (NULL);
740e4b17023SJohn Marino       gi->store2_p = BITMAP_ALLOC (NULL);
741e4b17023SJohn Marino       gi->escaped_p = BITMAP_ALLOC (NULL);
742e4b17023SJohn Marino       gi->escaped_n = BITMAP_ALLOC (NULL);
743e4b17023SJohn Marino       gi->group_kill = BITMAP_ALLOC (NULL);
744e4b17023SJohn Marino       gi->process_globally = false;
745e4b17023SJohn Marino       gi->frame_related =
746e4b17023SJohn Marino 	(base == frame_pointer_rtx) || (base == hard_frame_pointer_rtx);
747e4b17023SJohn Marino       gi->offset_map_size_n = 0;
748e4b17023SJohn Marino       gi->offset_map_size_p = 0;
749e4b17023SJohn Marino       gi->offset_map_n = NULL;
750e4b17023SJohn Marino       gi->offset_map_p = NULL;
751e4b17023SJohn Marino       VEC_safe_push (group_info_t, heap, rtx_group_vec, gi);
752e4b17023SJohn Marino     }
753e4b17023SJohn Marino 
754e4b17023SJohn Marino   return gi;
755e4b17023SJohn Marino }
756e4b17023SJohn Marino 
757e4b17023SJohn Marino 
758e4b17023SJohn Marino /* Initialization of data structures.  */
759e4b17023SJohn Marino 
760e4b17023SJohn Marino static void
dse_step0(void)761e4b17023SJohn Marino dse_step0 (void)
762e4b17023SJohn Marino {
763e4b17023SJohn Marino   locally_deleted = 0;
764e4b17023SJohn Marino   globally_deleted = 0;
765e4b17023SJohn Marino   spill_deleted = 0;
766e4b17023SJohn Marino 
767e4b17023SJohn Marino   scratch = BITMAP_ALLOC (NULL);
768e4b17023SJohn Marino   kill_on_calls = BITMAP_ALLOC (NULL);
769e4b17023SJohn Marino 
770e4b17023SJohn Marino   rtx_store_info_pool
771e4b17023SJohn Marino     = create_alloc_pool ("rtx_store_info_pool",
772e4b17023SJohn Marino 			 sizeof (struct store_info), 100);
773e4b17023SJohn Marino   read_info_pool
774e4b17023SJohn Marino     = create_alloc_pool ("read_info_pool",
775e4b17023SJohn Marino 			 sizeof (struct read_info), 100);
776e4b17023SJohn Marino   insn_info_pool
777e4b17023SJohn Marino     = create_alloc_pool ("insn_info_pool",
778e4b17023SJohn Marino 			 sizeof (struct insn_info), 100);
779e4b17023SJohn Marino   bb_info_pool
780e4b17023SJohn Marino     = create_alloc_pool ("bb_info_pool",
781e4b17023SJohn Marino 			 sizeof (struct bb_info), 100);
782e4b17023SJohn Marino   rtx_group_info_pool
783e4b17023SJohn Marino     = create_alloc_pool ("rtx_group_info_pool",
784e4b17023SJohn Marino 			 sizeof (struct group_info), 100);
785e4b17023SJohn Marino   deferred_change_pool
786e4b17023SJohn Marino     = create_alloc_pool ("deferred_change_pool",
787e4b17023SJohn Marino 			 sizeof (struct deferred_change), 10);
788e4b17023SJohn Marino 
789e4b17023SJohn Marino   rtx_group_table = htab_create (11, invariant_group_base_hash,
790e4b17023SJohn Marino 				 invariant_group_base_eq, NULL);
791e4b17023SJohn Marino 
792e4b17023SJohn Marino   bb_table = XCNEWVEC (bb_info_t, last_basic_block);
793e4b17023SJohn Marino   rtx_group_next_id = 0;
794e4b17023SJohn Marino 
795e4b17023SJohn Marino   stores_off_frame_dead_at_return = !cfun->stdarg;
796e4b17023SJohn Marino 
797e4b17023SJohn Marino   init_alias_analysis ();
798e4b17023SJohn Marino 
799e4b17023SJohn Marino   if (clear_alias_sets)
800e4b17023SJohn Marino     clear_alias_group = get_group_info (NULL);
801e4b17023SJohn Marino   else
802e4b17023SJohn Marino     clear_alias_group = NULL;
803e4b17023SJohn Marino }
804e4b17023SJohn Marino 
805e4b17023SJohn Marino 
806e4b17023SJohn Marino 
807e4b17023SJohn Marino /*----------------------------------------------------------------------------
808e4b17023SJohn Marino    First step.
809e4b17023SJohn Marino 
810e4b17023SJohn Marino    Scan all of the insns.  Any random ordering of the blocks is fine.
811e4b17023SJohn Marino    Each block is scanned in forward order to accommodate cselib which
812e4b17023SJohn Marino    is used to remove stores with non-constant bases.
813e4b17023SJohn Marino ----------------------------------------------------------------------------*/
814e4b17023SJohn Marino 
815e4b17023SJohn Marino /* Delete all of the store_info recs from INSN_INFO.  */
816e4b17023SJohn Marino 
817e4b17023SJohn Marino static void
free_store_info(insn_info_t insn_info)818e4b17023SJohn Marino free_store_info (insn_info_t insn_info)
819e4b17023SJohn Marino {
820e4b17023SJohn Marino   store_info_t store_info = insn_info->store_rec;
821e4b17023SJohn Marino   while (store_info)
822e4b17023SJohn Marino     {
823e4b17023SJohn Marino       store_info_t next = store_info->next;
824e4b17023SJohn Marino       if (store_info->is_large)
825e4b17023SJohn Marino 	BITMAP_FREE (store_info->positions_needed.large.bmap);
826e4b17023SJohn Marino       if (store_info->cse_base)
827e4b17023SJohn Marino 	pool_free (cse_store_info_pool, store_info);
828e4b17023SJohn Marino       else
829e4b17023SJohn Marino 	pool_free (rtx_store_info_pool, store_info);
830e4b17023SJohn Marino       store_info = next;
831e4b17023SJohn Marino     }
832e4b17023SJohn Marino 
833e4b17023SJohn Marino   insn_info->cannot_delete = true;
834e4b17023SJohn Marino   insn_info->contains_cselib_groups = false;
835e4b17023SJohn Marino   insn_info->store_rec = NULL;
836e4b17023SJohn Marino }
837e4b17023SJohn Marino 
838e4b17023SJohn Marino typedef struct
839e4b17023SJohn Marino {
840e4b17023SJohn Marino   rtx first, current;
841e4b17023SJohn Marino   regset fixed_regs_live;
842e4b17023SJohn Marino   bool failure;
843e4b17023SJohn Marino } note_add_store_info;
844e4b17023SJohn Marino 
845e4b17023SJohn Marino /* Callback for emit_inc_dec_insn_before via note_stores.
846e4b17023SJohn Marino    Check if a register is clobbered which is live afterwards.  */
847e4b17023SJohn Marino 
848e4b17023SJohn Marino static void
note_add_store(rtx loc,const_rtx expr ATTRIBUTE_UNUSED,void * data)849e4b17023SJohn Marino note_add_store (rtx loc, const_rtx expr ATTRIBUTE_UNUSED, void *data)
850e4b17023SJohn Marino {
851e4b17023SJohn Marino   rtx insn;
852e4b17023SJohn Marino   note_add_store_info *info = (note_add_store_info *) data;
853e4b17023SJohn Marino   int r, n;
854e4b17023SJohn Marino 
855e4b17023SJohn Marino   if (!REG_P (loc))
856e4b17023SJohn Marino     return;
857e4b17023SJohn Marino 
858e4b17023SJohn Marino   /* If this register is referenced by the current or an earlier insn,
859e4b17023SJohn Marino      that's OK.  E.g. this applies to the register that is being incremented
860e4b17023SJohn Marino      with this addition.  */
861e4b17023SJohn Marino   for (insn = info->first;
862e4b17023SJohn Marino        insn != NEXT_INSN (info->current);
863e4b17023SJohn Marino        insn = NEXT_INSN (insn))
864e4b17023SJohn Marino     if (reg_referenced_p (loc, PATTERN (insn)))
865e4b17023SJohn Marino       return;
866e4b17023SJohn Marino 
867e4b17023SJohn Marino   /* If we come here, we have a clobber of a register that's only OK
868e4b17023SJohn Marino      if that register is not live.  If we don't have liveness information
869e4b17023SJohn Marino      available, fail now.  */
870e4b17023SJohn Marino   if (!info->fixed_regs_live)
871e4b17023SJohn Marino     {
872e4b17023SJohn Marino       info->failure =  true;
873e4b17023SJohn Marino       return;
874e4b17023SJohn Marino     }
875e4b17023SJohn Marino   /* Now check if this is a live fixed register.  */
876e4b17023SJohn Marino   r = REGNO (loc);
877e4b17023SJohn Marino   n = hard_regno_nregs[r][GET_MODE (loc)];
878e4b17023SJohn Marino   while (--n >=  0)
879e4b17023SJohn Marino     if (REGNO_REG_SET_P (info->fixed_regs_live, r+n))
880e4b17023SJohn Marino       info->failure =  true;
881e4b17023SJohn Marino }
882e4b17023SJohn Marino 
883e4b17023SJohn Marino /* Callback for for_each_inc_dec that emits an INSN that sets DEST to
884e4b17023SJohn Marino    SRC + SRCOFF before insn ARG.  */
885e4b17023SJohn Marino 
886e4b17023SJohn Marino static int
emit_inc_dec_insn_before(rtx mem ATTRIBUTE_UNUSED,rtx op ATTRIBUTE_UNUSED,rtx dest,rtx src,rtx srcoff,void * arg)887e4b17023SJohn Marino emit_inc_dec_insn_before (rtx mem ATTRIBUTE_UNUSED,
888e4b17023SJohn Marino 			  rtx op ATTRIBUTE_UNUSED,
889e4b17023SJohn Marino 			  rtx dest, rtx src, rtx srcoff, void *arg)
890e4b17023SJohn Marino {
891e4b17023SJohn Marino   insn_info_t insn_info = (insn_info_t) arg;
892e4b17023SJohn Marino   rtx insn = insn_info->insn, new_insn, cur;
893e4b17023SJohn Marino   note_add_store_info info;
894e4b17023SJohn Marino 
895e4b17023SJohn Marino   /* We can reuse all operands without copying, because we are about
896e4b17023SJohn Marino      to delete the insn that contained it.  */
897e4b17023SJohn Marino   if (srcoff)
898e4b17023SJohn Marino     {
899e4b17023SJohn Marino       start_sequence ();
900e4b17023SJohn Marino       emit_insn (gen_add3_insn (dest, src, srcoff));
901e4b17023SJohn Marino       new_insn = get_insns ();
902e4b17023SJohn Marino       end_sequence ();
903e4b17023SJohn Marino     }
904e4b17023SJohn Marino   else
905e4b17023SJohn Marino     new_insn = gen_move_insn (dest, src);
906e4b17023SJohn Marino   info.first = new_insn;
907e4b17023SJohn Marino   info.fixed_regs_live = insn_info->fixed_regs_live;
908e4b17023SJohn Marino   info.failure = false;
909e4b17023SJohn Marino   for (cur = new_insn; cur; cur = NEXT_INSN (cur))
910e4b17023SJohn Marino     {
911e4b17023SJohn Marino       info.current = cur;
912e4b17023SJohn Marino       note_stores (PATTERN (cur), note_add_store, &info);
913e4b17023SJohn Marino     }
914e4b17023SJohn Marino 
915e4b17023SJohn Marino   /* If a failure was flagged above, return 1 so that for_each_inc_dec will
916e4b17023SJohn Marino      return it immediately, communicating the failure to its caller.  */
917e4b17023SJohn Marino   if (info.failure)
918e4b17023SJohn Marino     return 1;
919e4b17023SJohn Marino 
920e4b17023SJohn Marino   emit_insn_before (new_insn, insn);
921e4b17023SJohn Marino 
922e4b17023SJohn Marino   return -1;
923e4b17023SJohn Marino }
924e4b17023SJohn Marino 
925e4b17023SJohn Marino /* Before we delete INSN_INFO->INSN, make sure that the auto inc/dec, if it
926e4b17023SJohn Marino    is there, is split into a separate insn.
927e4b17023SJohn Marino    Return true on success (or if there was nothing to do), false on failure.  */
928e4b17023SJohn Marino 
929e4b17023SJohn Marino static bool
check_for_inc_dec_1(insn_info_t insn_info)930e4b17023SJohn Marino check_for_inc_dec_1 (insn_info_t insn_info)
931e4b17023SJohn Marino {
932e4b17023SJohn Marino   rtx insn = insn_info->insn;
933e4b17023SJohn Marino   rtx note = find_reg_note (insn, REG_INC, NULL_RTX);
934e4b17023SJohn Marino   if (note)
935e4b17023SJohn Marino     return for_each_inc_dec (&insn, emit_inc_dec_insn_before, insn_info) == 0;
936e4b17023SJohn Marino   return true;
937e4b17023SJohn Marino }
938e4b17023SJohn Marino 
939e4b17023SJohn Marino 
940e4b17023SJohn Marino /* Entry point for postreload.  If you work on reload_cse, or you need this
941e4b17023SJohn Marino    anywhere else, consider if you can provide register liveness information
942e4b17023SJohn Marino    and add a parameter to this function so that it can be passed down in
943e4b17023SJohn Marino    insn_info.fixed_regs_live.  */
944e4b17023SJohn Marino bool
check_for_inc_dec(rtx insn)945e4b17023SJohn Marino check_for_inc_dec (rtx insn)
946e4b17023SJohn Marino {
947e4b17023SJohn Marino   struct insn_info insn_info;
948e4b17023SJohn Marino   rtx note;
949e4b17023SJohn Marino 
950e4b17023SJohn Marino   insn_info.insn = insn;
951e4b17023SJohn Marino   insn_info.fixed_regs_live = NULL;
952e4b17023SJohn Marino   note = find_reg_note (insn, REG_INC, NULL_RTX);
953e4b17023SJohn Marino   if (note)
954e4b17023SJohn Marino     return for_each_inc_dec (&insn, emit_inc_dec_insn_before, &insn_info) == 0;
955e4b17023SJohn Marino   return true;
956e4b17023SJohn Marino }
957e4b17023SJohn Marino 
958e4b17023SJohn Marino /* Delete the insn and free all of the fields inside INSN_INFO.  */
959e4b17023SJohn Marino 
960e4b17023SJohn Marino static void
delete_dead_store_insn(insn_info_t insn_info)961e4b17023SJohn Marino delete_dead_store_insn (insn_info_t insn_info)
962e4b17023SJohn Marino {
963e4b17023SJohn Marino   read_info_t read_info;
964e4b17023SJohn Marino 
965e4b17023SJohn Marino   if (!dbg_cnt (dse))
966e4b17023SJohn Marino     return;
967e4b17023SJohn Marino 
968e4b17023SJohn Marino   if (!check_for_inc_dec_1 (insn_info))
969e4b17023SJohn Marino     return;
970e4b17023SJohn Marino   if (dump_file)
971e4b17023SJohn Marino     {
972e4b17023SJohn Marino       fprintf (dump_file, "Locally deleting insn %d ",
973e4b17023SJohn Marino 	       INSN_UID (insn_info->insn));
974e4b17023SJohn Marino       if (insn_info->store_rec->alias_set)
975e4b17023SJohn Marino 	fprintf (dump_file, "alias set %d\n",
976e4b17023SJohn Marino 		 (int) insn_info->store_rec->alias_set);
977e4b17023SJohn Marino       else
978e4b17023SJohn Marino 	fprintf (dump_file, "\n");
979e4b17023SJohn Marino     }
980e4b17023SJohn Marino 
981e4b17023SJohn Marino   free_store_info (insn_info);
982e4b17023SJohn Marino   read_info = insn_info->read_rec;
983e4b17023SJohn Marino 
984e4b17023SJohn Marino   while (read_info)
985e4b17023SJohn Marino     {
986e4b17023SJohn Marino       read_info_t next = read_info->next;
987e4b17023SJohn Marino       pool_free (read_info_pool, read_info);
988e4b17023SJohn Marino       read_info = next;
989e4b17023SJohn Marino     }
990e4b17023SJohn Marino   insn_info->read_rec = NULL;
991e4b17023SJohn Marino 
992e4b17023SJohn Marino   delete_insn (insn_info->insn);
993e4b17023SJohn Marino   locally_deleted++;
994e4b17023SJohn Marino   insn_info->insn = NULL;
995e4b17023SJohn Marino 
996e4b17023SJohn Marino   insn_info->wild_read = false;
997e4b17023SJohn Marino }
998e4b17023SJohn Marino 
999*5ce9237cSJohn Marino /* Return whether DECL, a local variable, can possibly escape the current
1000*5ce9237cSJohn Marino    function scope.  */
1001*5ce9237cSJohn Marino 
1002*5ce9237cSJohn Marino static bool
local_variable_can_escape(tree decl)1003*5ce9237cSJohn Marino local_variable_can_escape (tree decl)
1004*5ce9237cSJohn Marino {
1005*5ce9237cSJohn Marino   if (TREE_ADDRESSABLE (decl))
1006*5ce9237cSJohn Marino     return true;
1007*5ce9237cSJohn Marino 
1008*5ce9237cSJohn Marino   /* If this is a partitioned variable, we need to consider all the variables
1009*5ce9237cSJohn Marino      in the partition.  This is necessary because a store into one of them can
1010*5ce9237cSJohn Marino      be replaced with a store into another and this may not change the outcome
1011*5ce9237cSJohn Marino      of the escape analysis.  */
1012*5ce9237cSJohn Marino   if (cfun->gimple_df->decls_to_pointers != NULL)
1013*5ce9237cSJohn Marino     {
1014*5ce9237cSJohn Marino       void *namep
1015*5ce9237cSJohn Marino 	= pointer_map_contains (cfun->gimple_df->decls_to_pointers, decl);
1016*5ce9237cSJohn Marino       if (namep)
1017*5ce9237cSJohn Marino 	return TREE_ADDRESSABLE (*(tree *)namep);
1018*5ce9237cSJohn Marino     }
1019*5ce9237cSJohn Marino 
1020*5ce9237cSJohn Marino   return false;
1021*5ce9237cSJohn Marino }
1022*5ce9237cSJohn Marino 
1023*5ce9237cSJohn Marino /* Return whether EXPR can possibly escape the current function scope.  */
1024*5ce9237cSJohn Marino 
1025e4b17023SJohn Marino static bool
can_escape(tree expr)1026e4b17023SJohn Marino can_escape (tree expr)
1027e4b17023SJohn Marino {
1028e4b17023SJohn Marino   tree base;
1029e4b17023SJohn Marino   if (!expr)
1030e4b17023SJohn Marino     return true;
1031e4b17023SJohn Marino   base = get_base_address (expr);
1032e4b17023SJohn Marino   if (DECL_P (base)
1033*5ce9237cSJohn Marino       && !may_be_aliased (base)
1034*5ce9237cSJohn Marino       && !(TREE_CODE (base) == VAR_DECL
1035*5ce9237cSJohn Marino 	   && !DECL_EXTERNAL (base)
1036*5ce9237cSJohn Marino 	   && !TREE_STATIC (base)
1037*5ce9237cSJohn Marino 	   && local_variable_can_escape (base)))
1038e4b17023SJohn Marino     return false;
1039e4b17023SJohn Marino   return true;
1040e4b17023SJohn Marino }
1041e4b17023SJohn Marino 
1042e4b17023SJohn Marino /* Set the store* bitmaps offset_map_size* fields in GROUP based on
1043e4b17023SJohn Marino    OFFSET and WIDTH.  */
1044e4b17023SJohn Marino 
1045e4b17023SJohn Marino static void
set_usage_bits(group_info_t group,HOST_WIDE_INT offset,HOST_WIDE_INT width,tree expr)1046e4b17023SJohn Marino set_usage_bits (group_info_t group, HOST_WIDE_INT offset, HOST_WIDE_INT width,
1047e4b17023SJohn Marino                 tree expr)
1048e4b17023SJohn Marino {
1049e4b17023SJohn Marino   HOST_WIDE_INT i;
1050e4b17023SJohn Marino   bool expr_escapes = can_escape (expr);
1051e4b17023SJohn Marino   if (offset > -MAX_OFFSET && offset + width < MAX_OFFSET)
1052e4b17023SJohn Marino     for (i=offset; i<offset+width; i++)
1053e4b17023SJohn Marino       {
1054e4b17023SJohn Marino 	bitmap store1;
1055e4b17023SJohn Marino 	bitmap store2;
1056e4b17023SJohn Marino         bitmap escaped;
1057e4b17023SJohn Marino 	int ai;
1058e4b17023SJohn Marino 	if (i < 0)
1059e4b17023SJohn Marino 	  {
1060e4b17023SJohn Marino 	    store1 = group->store1_n;
1061e4b17023SJohn Marino 	    store2 = group->store2_n;
1062e4b17023SJohn Marino 	    escaped = group->escaped_n;
1063e4b17023SJohn Marino 	    ai = -i;
1064e4b17023SJohn Marino 	  }
1065e4b17023SJohn Marino 	else
1066e4b17023SJohn Marino 	  {
1067e4b17023SJohn Marino 	    store1 = group->store1_p;
1068e4b17023SJohn Marino 	    store2 = group->store2_p;
1069e4b17023SJohn Marino 	    escaped = group->escaped_p;
1070e4b17023SJohn Marino 	    ai = i;
1071e4b17023SJohn Marino 	  }
1072e4b17023SJohn Marino 
1073e4b17023SJohn Marino 	if (!bitmap_set_bit (store1, ai))
1074e4b17023SJohn Marino 	  bitmap_set_bit (store2, ai);
1075e4b17023SJohn Marino 	else
1076e4b17023SJohn Marino 	  {
1077e4b17023SJohn Marino 	    if (i < 0)
1078e4b17023SJohn Marino 	      {
1079e4b17023SJohn Marino 		if (group->offset_map_size_n < ai)
1080e4b17023SJohn Marino 		  group->offset_map_size_n = ai;
1081e4b17023SJohn Marino 	      }
1082e4b17023SJohn Marino 	    else
1083e4b17023SJohn Marino 	      {
1084e4b17023SJohn Marino 		if (group->offset_map_size_p < ai)
1085e4b17023SJohn Marino 		  group->offset_map_size_p = ai;
1086e4b17023SJohn Marino 	      }
1087e4b17023SJohn Marino 	  }
1088e4b17023SJohn Marino         if (expr_escapes)
1089e4b17023SJohn Marino           bitmap_set_bit (escaped, ai);
1090e4b17023SJohn Marino       }
1091e4b17023SJohn Marino }
1092e4b17023SJohn Marino 
1093e4b17023SJohn Marino static void
reset_active_stores(void)1094e4b17023SJohn Marino reset_active_stores (void)
1095e4b17023SJohn Marino {
1096e4b17023SJohn Marino   active_local_stores = NULL;
1097e4b17023SJohn Marino   active_local_stores_len = 0;
1098e4b17023SJohn Marino }
1099e4b17023SJohn Marino 
1100e4b17023SJohn Marino /* Free all READ_REC of the LAST_INSN of BB_INFO.  */
1101e4b17023SJohn Marino 
1102e4b17023SJohn Marino static void
free_read_records(bb_info_t bb_info)1103e4b17023SJohn Marino free_read_records (bb_info_t bb_info)
1104e4b17023SJohn Marino {
1105e4b17023SJohn Marino   insn_info_t insn_info = bb_info->last_insn;
1106e4b17023SJohn Marino   read_info_t *ptr = &insn_info->read_rec;
1107e4b17023SJohn Marino   while (*ptr)
1108e4b17023SJohn Marino     {
1109e4b17023SJohn Marino       read_info_t next = (*ptr)->next;
1110e4b17023SJohn Marino       if ((*ptr)->alias_set == 0)
1111e4b17023SJohn Marino         {
1112e4b17023SJohn Marino           pool_free (read_info_pool, *ptr);
1113e4b17023SJohn Marino           *ptr = next;
1114e4b17023SJohn Marino         }
1115e4b17023SJohn Marino       else
1116e4b17023SJohn Marino         ptr = &(*ptr)->next;
1117e4b17023SJohn Marino     }
1118e4b17023SJohn Marino }
1119e4b17023SJohn Marino 
1120e4b17023SJohn Marino /* Set the BB_INFO so that the last insn is marked as a wild read.  */
1121e4b17023SJohn Marino 
1122e4b17023SJohn Marino static void
add_wild_read(bb_info_t bb_info)1123e4b17023SJohn Marino add_wild_read (bb_info_t bb_info)
1124e4b17023SJohn Marino {
1125e4b17023SJohn Marino   insn_info_t insn_info = bb_info->last_insn;
1126e4b17023SJohn Marino   insn_info->wild_read = true;
1127e4b17023SJohn Marino   free_read_records (bb_info);
1128e4b17023SJohn Marino   reset_active_stores ();
1129e4b17023SJohn Marino }
1130e4b17023SJohn Marino 
1131e4b17023SJohn Marino /* Set the BB_INFO so that the last insn is marked as a wild read of
1132e4b17023SJohn Marino    non-frame locations.  */
1133e4b17023SJohn Marino 
1134e4b17023SJohn Marino static void
add_non_frame_wild_read(bb_info_t bb_info)1135e4b17023SJohn Marino add_non_frame_wild_read (bb_info_t bb_info)
1136e4b17023SJohn Marino {
1137e4b17023SJohn Marino   insn_info_t insn_info = bb_info->last_insn;
1138e4b17023SJohn Marino   insn_info->non_frame_wild_read = true;
1139e4b17023SJohn Marino   free_read_records (bb_info);
1140e4b17023SJohn Marino   reset_active_stores ();
1141e4b17023SJohn Marino }
1142e4b17023SJohn Marino 
1143e4b17023SJohn Marino /* Return true if X is a constant or one of the registers that behave
1144e4b17023SJohn Marino    as a constant over the life of a function.  This is equivalent to
1145e4b17023SJohn Marino    !rtx_varies_p for memory addresses.  */
1146e4b17023SJohn Marino 
1147e4b17023SJohn Marino static bool
const_or_frame_p(rtx x)1148e4b17023SJohn Marino const_or_frame_p (rtx x)
1149e4b17023SJohn Marino {
1150e4b17023SJohn Marino   switch (GET_CODE (x))
1151e4b17023SJohn Marino     {
1152e4b17023SJohn Marino     case CONST:
1153e4b17023SJohn Marino     case CONST_INT:
1154e4b17023SJohn Marino     case CONST_DOUBLE:
1155e4b17023SJohn Marino     case CONST_VECTOR:
1156e4b17023SJohn Marino     case SYMBOL_REF:
1157e4b17023SJohn Marino     case LABEL_REF:
1158e4b17023SJohn Marino       return true;
1159e4b17023SJohn Marino 
1160e4b17023SJohn Marino     case REG:
1161e4b17023SJohn Marino       /* Note that we have to test for the actual rtx used for the frame
1162e4b17023SJohn Marino 	 and arg pointers and not just the register number in case we have
1163e4b17023SJohn Marino 	 eliminated the frame and/or arg pointer and are using it
1164e4b17023SJohn Marino 	 for pseudos.  */
1165e4b17023SJohn Marino       if (x == frame_pointer_rtx || x == hard_frame_pointer_rtx
1166e4b17023SJohn Marino 	  /* The arg pointer varies if it is not a fixed register.  */
1167e4b17023SJohn Marino 	  || (x == arg_pointer_rtx && fixed_regs[ARG_POINTER_REGNUM])
1168e4b17023SJohn Marino 	  || x == pic_offset_table_rtx)
1169e4b17023SJohn Marino 	return true;
1170e4b17023SJohn Marino       return false;
1171e4b17023SJohn Marino 
1172e4b17023SJohn Marino     default:
1173e4b17023SJohn Marino       return false;
1174e4b17023SJohn Marino     }
1175e4b17023SJohn Marino }
1176e4b17023SJohn Marino 
1177e4b17023SJohn Marino /* Take all reasonable action to put the address of MEM into the form
1178e4b17023SJohn Marino    that we can do analysis on.
1179e4b17023SJohn Marino 
1180e4b17023SJohn Marino    The gold standard is to get the address into the form: address +
1181e4b17023SJohn Marino    OFFSET where address is something that rtx_varies_p considers a
1182e4b17023SJohn Marino    constant.  When we can get the address in this form, we can do
1183e4b17023SJohn Marino    global analysis on it.  Note that for constant bases, address is
1184e4b17023SJohn Marino    not actually returned, only the group_id.  The address can be
1185e4b17023SJohn Marino    obtained from that.
1186e4b17023SJohn Marino 
1187e4b17023SJohn Marino    If that fails, we try cselib to get a value we can at least use
1188e4b17023SJohn Marino    locally.  If that fails we return false.
1189e4b17023SJohn Marino 
1190e4b17023SJohn Marino    The GROUP_ID is set to -1 for cselib bases and the index of the
1191e4b17023SJohn Marino    group for non_varying bases.
1192e4b17023SJohn Marino 
1193e4b17023SJohn Marino    FOR_READ is true if this is a mem read and false if not.  */
1194e4b17023SJohn Marino 
1195e4b17023SJohn Marino static bool
canon_address(rtx mem,alias_set_type * alias_set_out,int * group_id,HOST_WIDE_INT * offset,cselib_val ** base)1196e4b17023SJohn Marino canon_address (rtx mem,
1197e4b17023SJohn Marino 	       alias_set_type *alias_set_out,
1198e4b17023SJohn Marino 	       int *group_id,
1199e4b17023SJohn Marino 	       HOST_WIDE_INT *offset,
1200e4b17023SJohn Marino 	       cselib_val **base)
1201e4b17023SJohn Marino {
1202e4b17023SJohn Marino   enum machine_mode address_mode
1203e4b17023SJohn Marino     = targetm.addr_space.address_mode (MEM_ADDR_SPACE (mem));
1204e4b17023SJohn Marino   rtx mem_address = XEXP (mem, 0);
1205e4b17023SJohn Marino   rtx expanded_address, address;
1206e4b17023SJohn Marino   int expanded;
1207e4b17023SJohn Marino 
1208e4b17023SJohn Marino   /* Make sure that cselib is has initialized all of the operands of
1209e4b17023SJohn Marino      the address before asking it to do the subst.  */
1210e4b17023SJohn Marino 
1211e4b17023SJohn Marino   if (clear_alias_sets)
1212e4b17023SJohn Marino     {
1213e4b17023SJohn Marino       /* If this is a spill, do not do any further processing.  */
1214e4b17023SJohn Marino       alias_set_type alias_set = MEM_ALIAS_SET (mem);
1215e4b17023SJohn Marino       if (dump_file)
1216e4b17023SJohn Marino 	fprintf (dump_file, "found alias set %d\n", (int) alias_set);
1217e4b17023SJohn Marino       if (bitmap_bit_p (clear_alias_sets, alias_set))
1218e4b17023SJohn Marino 	{
1219e4b17023SJohn Marino 	  struct clear_alias_mode_holder *entry
1220e4b17023SJohn Marino 	    = clear_alias_set_lookup (alias_set);
1221e4b17023SJohn Marino 
1222e4b17023SJohn Marino 	  /* If the modes do not match, we cannot process this set.  */
1223e4b17023SJohn Marino 	  if (entry->mode != GET_MODE (mem))
1224e4b17023SJohn Marino 	    {
1225e4b17023SJohn Marino 	      if (dump_file)
1226e4b17023SJohn Marino 		fprintf (dump_file,
1227e4b17023SJohn Marino 			 "disqualifying alias set %d, (%s) != (%s)\n",
1228e4b17023SJohn Marino 			 (int) alias_set, GET_MODE_NAME (entry->mode),
1229e4b17023SJohn Marino 			 GET_MODE_NAME (GET_MODE (mem)));
1230e4b17023SJohn Marino 
1231e4b17023SJohn Marino 	      bitmap_set_bit (disqualified_clear_alias_sets, alias_set);
1232e4b17023SJohn Marino 	      return false;
1233e4b17023SJohn Marino 	    }
1234e4b17023SJohn Marino 
1235e4b17023SJohn Marino 	  *alias_set_out = alias_set;
1236e4b17023SJohn Marino 	  *group_id = clear_alias_group->id;
1237e4b17023SJohn Marino 	  return true;
1238e4b17023SJohn Marino 	}
1239e4b17023SJohn Marino     }
1240e4b17023SJohn Marino 
1241e4b17023SJohn Marino   *alias_set_out = 0;
1242e4b17023SJohn Marino 
1243e4b17023SJohn Marino   cselib_lookup (mem_address, address_mode, 1, GET_MODE (mem));
1244e4b17023SJohn Marino 
1245e4b17023SJohn Marino   if (dump_file)
1246e4b17023SJohn Marino     {
1247e4b17023SJohn Marino       fprintf (dump_file, "  mem: ");
1248e4b17023SJohn Marino       print_inline_rtx (dump_file, mem_address, 0);
1249e4b17023SJohn Marino       fprintf (dump_file, "\n");
1250e4b17023SJohn Marino     }
1251e4b17023SJohn Marino 
1252e4b17023SJohn Marino   /* First see if just canon_rtx (mem_address) is const or frame,
1253e4b17023SJohn Marino      if not, try cselib_expand_value_rtx and call canon_rtx on that.  */
1254e4b17023SJohn Marino   address = NULL_RTX;
1255e4b17023SJohn Marino   for (expanded = 0; expanded < 2; expanded++)
1256e4b17023SJohn Marino     {
1257e4b17023SJohn Marino       if (expanded)
1258e4b17023SJohn Marino 	{
1259e4b17023SJohn Marino 	  /* Use cselib to replace all of the reg references with the full
1260e4b17023SJohn Marino 	     expression.  This will take care of the case where we have
1261e4b17023SJohn Marino 
1262e4b17023SJohn Marino 	     r_x = base + offset;
1263e4b17023SJohn Marino 	     val = *r_x;
1264e4b17023SJohn Marino 
1265e4b17023SJohn Marino 	     by making it into
1266e4b17023SJohn Marino 
1267e4b17023SJohn Marino 	     val = *(base + offset);  */
1268e4b17023SJohn Marino 
1269e4b17023SJohn Marino 	  expanded_address = cselib_expand_value_rtx (mem_address,
1270e4b17023SJohn Marino 						      scratch, 5);
1271e4b17023SJohn Marino 
1272e4b17023SJohn Marino 	  /* If this fails, just go with the address from first
1273e4b17023SJohn Marino 	     iteration.  */
1274e4b17023SJohn Marino 	  if (!expanded_address)
1275e4b17023SJohn Marino 	    break;
1276e4b17023SJohn Marino 	}
1277e4b17023SJohn Marino       else
1278e4b17023SJohn Marino 	expanded_address = mem_address;
1279e4b17023SJohn Marino 
1280e4b17023SJohn Marino       /* Split the address into canonical BASE + OFFSET terms.  */
1281e4b17023SJohn Marino       address = canon_rtx (expanded_address);
1282e4b17023SJohn Marino 
1283e4b17023SJohn Marino       *offset = 0;
1284e4b17023SJohn Marino 
1285e4b17023SJohn Marino       if (dump_file)
1286e4b17023SJohn Marino 	{
1287e4b17023SJohn Marino 	  if (expanded)
1288e4b17023SJohn Marino 	    {
1289e4b17023SJohn Marino 	      fprintf (dump_file, "\n   after cselib_expand address: ");
1290e4b17023SJohn Marino 	      print_inline_rtx (dump_file, expanded_address, 0);
1291e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
1292e4b17023SJohn Marino 	    }
1293e4b17023SJohn Marino 
1294e4b17023SJohn Marino 	  fprintf (dump_file, "\n   after canon_rtx address: ");
1295e4b17023SJohn Marino 	  print_inline_rtx (dump_file, address, 0);
1296e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
1297e4b17023SJohn Marino 	}
1298e4b17023SJohn Marino 
1299e4b17023SJohn Marino       if (GET_CODE (address) == CONST)
1300e4b17023SJohn Marino 	address = XEXP (address, 0);
1301e4b17023SJohn Marino 
1302e4b17023SJohn Marino       if (GET_CODE (address) == PLUS
1303e4b17023SJohn Marino 	  && CONST_INT_P (XEXP (address, 1)))
1304e4b17023SJohn Marino 	{
1305e4b17023SJohn Marino 	  *offset = INTVAL (XEXP (address, 1));
1306e4b17023SJohn Marino 	  address = XEXP (address, 0);
1307e4b17023SJohn Marino 	}
1308e4b17023SJohn Marino 
1309e4b17023SJohn Marino       if (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (mem))
1310e4b17023SJohn Marino 	  && const_or_frame_p (address))
1311e4b17023SJohn Marino 	{
1312e4b17023SJohn Marino 	  group_info_t group = get_group_info (address);
1313e4b17023SJohn Marino 
1314e4b17023SJohn Marino 	  if (dump_file)
1315e4b17023SJohn Marino 	    fprintf (dump_file, "  gid=%d offset=%d \n",
1316e4b17023SJohn Marino 		     group->id, (int)*offset);
1317e4b17023SJohn Marino 	  *base = NULL;
1318e4b17023SJohn Marino 	  *group_id = group->id;
1319e4b17023SJohn Marino 	  return true;
1320e4b17023SJohn Marino 	}
1321e4b17023SJohn Marino     }
1322e4b17023SJohn Marino 
1323e4b17023SJohn Marino   *base = cselib_lookup (address, address_mode, true, GET_MODE (mem));
1324e4b17023SJohn Marino   *group_id = -1;
1325e4b17023SJohn Marino 
1326e4b17023SJohn Marino   if (*base == NULL)
1327e4b17023SJohn Marino     {
1328e4b17023SJohn Marino       if (dump_file)
1329e4b17023SJohn Marino 	fprintf (dump_file, " no cselib val - should be a wild read.\n");
1330e4b17023SJohn Marino       return false;
1331e4b17023SJohn Marino     }
1332e4b17023SJohn Marino   if (dump_file)
1333e4b17023SJohn Marino     fprintf (dump_file, "  varying cselib base=%u:%u offset = %d\n",
1334e4b17023SJohn Marino 	     (*base)->uid, (*base)->hash, (int)*offset);
1335e4b17023SJohn Marino   return true;
1336e4b17023SJohn Marino }
1337e4b17023SJohn Marino 
1338e4b17023SJohn Marino 
1339e4b17023SJohn Marino /* Clear the rhs field from the active_local_stores array.  */
1340e4b17023SJohn Marino 
1341e4b17023SJohn Marino static void
clear_rhs_from_active_local_stores(void)1342e4b17023SJohn Marino clear_rhs_from_active_local_stores (void)
1343e4b17023SJohn Marino {
1344e4b17023SJohn Marino   insn_info_t ptr = active_local_stores;
1345e4b17023SJohn Marino 
1346e4b17023SJohn Marino   while (ptr)
1347e4b17023SJohn Marino     {
1348e4b17023SJohn Marino       store_info_t store_info = ptr->store_rec;
1349e4b17023SJohn Marino       /* Skip the clobbers.  */
1350e4b17023SJohn Marino       while (!store_info->is_set)
1351e4b17023SJohn Marino 	store_info = store_info->next;
1352e4b17023SJohn Marino 
1353e4b17023SJohn Marino       store_info->rhs = NULL;
1354e4b17023SJohn Marino       store_info->const_rhs = NULL;
1355e4b17023SJohn Marino 
1356e4b17023SJohn Marino       ptr = ptr->next_local_store;
1357e4b17023SJohn Marino     }
1358e4b17023SJohn Marino }
1359e4b17023SJohn Marino 
1360e4b17023SJohn Marino 
1361e4b17023SJohn Marino /* Mark byte POS bytes from the beginning of store S_INFO as unneeded.  */
1362e4b17023SJohn Marino 
1363e4b17023SJohn Marino static inline void
set_position_unneeded(store_info_t s_info,int pos)1364e4b17023SJohn Marino set_position_unneeded (store_info_t s_info, int pos)
1365e4b17023SJohn Marino {
1366e4b17023SJohn Marino   if (__builtin_expect (s_info->is_large, false))
1367e4b17023SJohn Marino     {
1368e4b17023SJohn Marino       if (bitmap_set_bit (s_info->positions_needed.large.bmap, pos))
1369e4b17023SJohn Marino 	s_info->positions_needed.large.count++;
1370e4b17023SJohn Marino     }
1371e4b17023SJohn Marino   else
1372e4b17023SJohn Marino     s_info->positions_needed.small_bitmask
1373e4b17023SJohn Marino       &= ~(((unsigned HOST_WIDE_INT) 1) << pos);
1374e4b17023SJohn Marino }
1375e4b17023SJohn Marino 
1376e4b17023SJohn Marino /* Mark the whole store S_INFO as unneeded.  */
1377e4b17023SJohn Marino 
1378e4b17023SJohn Marino static inline void
set_all_positions_unneeded(store_info_t s_info)1379e4b17023SJohn Marino set_all_positions_unneeded (store_info_t s_info)
1380e4b17023SJohn Marino {
1381e4b17023SJohn Marino   if (__builtin_expect (s_info->is_large, false))
1382e4b17023SJohn Marino     {
1383e4b17023SJohn Marino       int pos, end = s_info->end - s_info->begin;
1384e4b17023SJohn Marino       for (pos = 0; pos < end; pos++)
1385e4b17023SJohn Marino 	bitmap_set_bit (s_info->positions_needed.large.bmap, pos);
1386e4b17023SJohn Marino       s_info->positions_needed.large.count = end;
1387e4b17023SJohn Marino     }
1388e4b17023SJohn Marino   else
1389e4b17023SJohn Marino     s_info->positions_needed.small_bitmask = (unsigned HOST_WIDE_INT) 0;
1390e4b17023SJohn Marino }
1391e4b17023SJohn Marino 
1392e4b17023SJohn Marino /* Return TRUE if any bytes from S_INFO store are needed.  */
1393e4b17023SJohn Marino 
1394e4b17023SJohn Marino static inline bool
any_positions_needed_p(store_info_t s_info)1395e4b17023SJohn Marino any_positions_needed_p (store_info_t s_info)
1396e4b17023SJohn Marino {
1397e4b17023SJohn Marino   if (__builtin_expect (s_info->is_large, false))
1398e4b17023SJohn Marino     return (s_info->positions_needed.large.count
1399e4b17023SJohn Marino 	    < s_info->end - s_info->begin);
1400e4b17023SJohn Marino   else
1401e4b17023SJohn Marino     return (s_info->positions_needed.small_bitmask
1402e4b17023SJohn Marino 	    != (unsigned HOST_WIDE_INT) 0);
1403e4b17023SJohn Marino }
1404e4b17023SJohn Marino 
1405e4b17023SJohn Marino /* Return TRUE if all bytes START through START+WIDTH-1 from S_INFO
1406e4b17023SJohn Marino    store are needed.  */
1407e4b17023SJohn Marino 
1408e4b17023SJohn Marino static inline bool
all_positions_needed_p(store_info_t s_info,int start,int width)1409e4b17023SJohn Marino all_positions_needed_p (store_info_t s_info, int start, int width)
1410e4b17023SJohn Marino {
1411e4b17023SJohn Marino   if (__builtin_expect (s_info->is_large, false))
1412e4b17023SJohn Marino     {
1413e4b17023SJohn Marino       int end = start + width;
1414e4b17023SJohn Marino       while (start < end)
1415e4b17023SJohn Marino 	if (bitmap_bit_p (s_info->positions_needed.large.bmap, start++))
1416e4b17023SJohn Marino 	  return false;
1417e4b17023SJohn Marino       return true;
1418e4b17023SJohn Marino     }
1419e4b17023SJohn Marino   else
1420e4b17023SJohn Marino     {
1421e4b17023SJohn Marino       unsigned HOST_WIDE_INT mask = lowpart_bitmask (width) << start;
1422e4b17023SJohn Marino       return (s_info->positions_needed.small_bitmask & mask) == mask;
1423e4b17023SJohn Marino     }
1424e4b17023SJohn Marino }
1425e4b17023SJohn Marino 
1426e4b17023SJohn Marino 
1427e4b17023SJohn Marino static rtx get_stored_val (store_info_t, enum machine_mode, HOST_WIDE_INT,
1428e4b17023SJohn Marino 			   HOST_WIDE_INT, basic_block, bool);
1429e4b17023SJohn Marino 
1430e4b17023SJohn Marino 
1431e4b17023SJohn Marino /* BODY is an instruction pattern that belongs to INSN.  Return 1 if
1432e4b17023SJohn Marino    there is a candidate store, after adding it to the appropriate
1433e4b17023SJohn Marino    local store group if so.  */
1434e4b17023SJohn Marino 
1435e4b17023SJohn Marino static int
record_store(rtx body,bb_info_t bb_info)1436e4b17023SJohn Marino record_store (rtx body, bb_info_t bb_info)
1437e4b17023SJohn Marino {
1438e4b17023SJohn Marino   rtx mem, rhs, const_rhs, mem_addr;
1439e4b17023SJohn Marino   HOST_WIDE_INT offset = 0;
1440e4b17023SJohn Marino   HOST_WIDE_INT width = 0;
1441e4b17023SJohn Marino   alias_set_type spill_alias_set;
1442e4b17023SJohn Marino   insn_info_t insn_info = bb_info->last_insn;
1443e4b17023SJohn Marino   store_info_t store_info = NULL;
1444e4b17023SJohn Marino   int group_id;
1445e4b17023SJohn Marino   cselib_val *base = NULL;
1446e4b17023SJohn Marino   insn_info_t ptr, last, redundant_reason;
1447e4b17023SJohn Marino   bool store_is_unused;
1448e4b17023SJohn Marino 
1449e4b17023SJohn Marino   if (GET_CODE (body) != SET && GET_CODE (body) != CLOBBER)
1450e4b17023SJohn Marino     return 0;
1451e4b17023SJohn Marino 
1452e4b17023SJohn Marino   mem = SET_DEST (body);
1453e4b17023SJohn Marino 
1454e4b17023SJohn Marino   /* If this is not used, then this cannot be used to keep the insn
1455e4b17023SJohn Marino      from being deleted.  On the other hand, it does provide something
1456e4b17023SJohn Marino      that can be used to prove that another store is dead.  */
1457e4b17023SJohn Marino   store_is_unused
1458e4b17023SJohn Marino     = (find_reg_note (insn_info->insn, REG_UNUSED, mem) != NULL);
1459e4b17023SJohn Marino 
1460e4b17023SJohn Marino   /* Check whether that value is a suitable memory location.  */
1461e4b17023SJohn Marino   if (!MEM_P (mem))
1462e4b17023SJohn Marino     {
1463e4b17023SJohn Marino       /* If the set or clobber is unused, then it does not effect our
1464e4b17023SJohn Marino 	 ability to get rid of the entire insn.  */
1465e4b17023SJohn Marino       if (!store_is_unused)
1466e4b17023SJohn Marino 	insn_info->cannot_delete = true;
1467e4b17023SJohn Marino       return 0;
1468e4b17023SJohn Marino     }
1469e4b17023SJohn Marino 
1470e4b17023SJohn Marino   /* At this point we know mem is a mem. */
1471e4b17023SJohn Marino   if (GET_MODE (mem) == BLKmode)
1472e4b17023SJohn Marino     {
1473e4b17023SJohn Marino       if (GET_CODE (XEXP (mem, 0)) == SCRATCH)
1474e4b17023SJohn Marino 	{
1475e4b17023SJohn Marino 	  if (dump_file)
1476e4b17023SJohn Marino 	    fprintf (dump_file, " adding wild read for (clobber (mem:BLK (scratch))\n");
1477e4b17023SJohn Marino 	  add_wild_read (bb_info);
1478e4b17023SJohn Marino 	  insn_info->cannot_delete = true;
1479e4b17023SJohn Marino 	  return 0;
1480e4b17023SJohn Marino 	}
1481e4b17023SJohn Marino       /* Handle (set (mem:BLK (addr) [... S36 ...]) (const_int 0))
1482e4b17023SJohn Marino 	 as memset (addr, 0, 36);  */
1483e4b17023SJohn Marino       else if (!MEM_SIZE_KNOWN_P (mem)
1484e4b17023SJohn Marino 	       || MEM_SIZE (mem) <= 0
1485e4b17023SJohn Marino 	       || MEM_SIZE (mem) > MAX_OFFSET
1486e4b17023SJohn Marino 	       || GET_CODE (body) != SET
1487e4b17023SJohn Marino 	       || !CONST_INT_P (SET_SRC (body)))
1488e4b17023SJohn Marino 	{
1489e4b17023SJohn Marino 	  if (!store_is_unused)
1490e4b17023SJohn Marino 	    {
1491e4b17023SJohn Marino 	      /* If the set or clobber is unused, then it does not effect our
1492e4b17023SJohn Marino 		 ability to get rid of the entire insn.  */
1493e4b17023SJohn Marino 	      insn_info->cannot_delete = true;
1494e4b17023SJohn Marino 	      clear_rhs_from_active_local_stores ();
1495e4b17023SJohn Marino 	    }
1496e4b17023SJohn Marino 	  return 0;
1497e4b17023SJohn Marino 	}
1498e4b17023SJohn Marino     }
1499e4b17023SJohn Marino 
1500e4b17023SJohn Marino   /* We can still process a volatile mem, we just cannot delete it.  */
1501e4b17023SJohn Marino   if (MEM_VOLATILE_P (mem))
1502e4b17023SJohn Marino     insn_info->cannot_delete = true;
1503e4b17023SJohn Marino 
1504e4b17023SJohn Marino   if (!canon_address (mem, &spill_alias_set, &group_id, &offset, &base))
1505e4b17023SJohn Marino     {
1506e4b17023SJohn Marino       clear_rhs_from_active_local_stores ();
1507e4b17023SJohn Marino       return 0;
1508e4b17023SJohn Marino     }
1509e4b17023SJohn Marino 
1510e4b17023SJohn Marino   if (GET_MODE (mem) == BLKmode)
1511e4b17023SJohn Marino     width = MEM_SIZE (mem);
1512e4b17023SJohn Marino   else
1513e4b17023SJohn Marino     {
1514e4b17023SJohn Marino       width = GET_MODE_SIZE (GET_MODE (mem));
1515e4b17023SJohn Marino       gcc_assert ((unsigned) width <= HOST_BITS_PER_WIDE_INT);
1516e4b17023SJohn Marino     }
1517e4b17023SJohn Marino 
1518e4b17023SJohn Marino   if (spill_alias_set)
1519e4b17023SJohn Marino     {
1520e4b17023SJohn Marino       bitmap store1 = clear_alias_group->store1_p;
1521e4b17023SJohn Marino       bitmap store2 = clear_alias_group->store2_p;
1522e4b17023SJohn Marino 
1523e4b17023SJohn Marino       gcc_assert (GET_MODE (mem) != BLKmode);
1524e4b17023SJohn Marino 
1525e4b17023SJohn Marino       if (!bitmap_set_bit (store1, spill_alias_set))
1526e4b17023SJohn Marino 	bitmap_set_bit (store2, spill_alias_set);
1527e4b17023SJohn Marino 
1528e4b17023SJohn Marino       if (clear_alias_group->offset_map_size_p < spill_alias_set)
1529e4b17023SJohn Marino 	clear_alias_group->offset_map_size_p = spill_alias_set;
1530e4b17023SJohn Marino 
1531e4b17023SJohn Marino       store_info = (store_info_t) pool_alloc (rtx_store_info_pool);
1532e4b17023SJohn Marino 
1533e4b17023SJohn Marino       if (dump_file)
1534e4b17023SJohn Marino 	fprintf (dump_file, " processing spill store %d(%s)\n",
1535e4b17023SJohn Marino 		 (int) spill_alias_set, GET_MODE_NAME (GET_MODE (mem)));
1536e4b17023SJohn Marino     }
1537e4b17023SJohn Marino   else if (group_id >= 0)
1538e4b17023SJohn Marino     {
1539e4b17023SJohn Marino       /* In the restrictive case where the base is a constant or the
1540e4b17023SJohn Marino 	 frame pointer we can do global analysis.  */
1541e4b17023SJohn Marino 
1542e4b17023SJohn Marino       group_info_t group
1543e4b17023SJohn Marino 	= VEC_index (group_info_t, rtx_group_vec, group_id);
1544e4b17023SJohn Marino       tree expr = MEM_EXPR (mem);
1545e4b17023SJohn Marino 
1546e4b17023SJohn Marino       store_info = (store_info_t) pool_alloc (rtx_store_info_pool);
1547e4b17023SJohn Marino       set_usage_bits (group, offset, width, expr);
1548e4b17023SJohn Marino 
1549e4b17023SJohn Marino       if (dump_file)
1550e4b17023SJohn Marino 	fprintf (dump_file, " processing const base store gid=%d[%d..%d)\n",
1551e4b17023SJohn Marino 		 group_id, (int)offset, (int)(offset+width));
1552e4b17023SJohn Marino     }
1553e4b17023SJohn Marino   else
1554e4b17023SJohn Marino     {
1555e4b17023SJohn Marino       rtx base_term = find_base_term (XEXP (mem, 0));
1556e4b17023SJohn Marino       if (!base_term
1557e4b17023SJohn Marino 	  || (GET_CODE (base_term) == ADDRESS
1558e4b17023SJohn Marino 	      && GET_MODE (base_term) == Pmode
1559e4b17023SJohn Marino 	      && XEXP (base_term, 0) == stack_pointer_rtx))
1560e4b17023SJohn Marino 	insn_info->stack_pointer_based = true;
1561e4b17023SJohn Marino       insn_info->contains_cselib_groups = true;
1562e4b17023SJohn Marino 
1563e4b17023SJohn Marino       store_info = (store_info_t) pool_alloc (cse_store_info_pool);
1564e4b17023SJohn Marino       group_id = -1;
1565e4b17023SJohn Marino 
1566e4b17023SJohn Marino       if (dump_file)
1567e4b17023SJohn Marino 	fprintf (dump_file, " processing cselib store [%d..%d)\n",
1568e4b17023SJohn Marino 		 (int)offset, (int)(offset+width));
1569e4b17023SJohn Marino     }
1570e4b17023SJohn Marino 
1571e4b17023SJohn Marino   const_rhs = rhs = NULL_RTX;
1572e4b17023SJohn Marino   if (GET_CODE (body) == SET
1573e4b17023SJohn Marino       /* No place to keep the value after ra.  */
1574e4b17023SJohn Marino       && !reload_completed
1575e4b17023SJohn Marino       && (REG_P (SET_SRC (body))
1576e4b17023SJohn Marino 	  || GET_CODE (SET_SRC (body)) == SUBREG
1577e4b17023SJohn Marino 	  || CONSTANT_P (SET_SRC (body)))
1578e4b17023SJohn Marino       && !MEM_VOLATILE_P (mem)
1579e4b17023SJohn Marino       /* Sometimes the store and reload is used for truncation and
1580e4b17023SJohn Marino 	 rounding.  */
1581e4b17023SJohn Marino       && !(FLOAT_MODE_P (GET_MODE (mem)) && (flag_float_store)))
1582e4b17023SJohn Marino     {
1583e4b17023SJohn Marino       rhs = SET_SRC (body);
1584e4b17023SJohn Marino       if (CONSTANT_P (rhs))
1585e4b17023SJohn Marino 	const_rhs = rhs;
1586e4b17023SJohn Marino       else if (body == PATTERN (insn_info->insn))
1587e4b17023SJohn Marino 	{
1588e4b17023SJohn Marino 	  rtx tem = find_reg_note (insn_info->insn, REG_EQUAL, NULL_RTX);
1589e4b17023SJohn Marino 	  if (tem && CONSTANT_P (XEXP (tem, 0)))
1590e4b17023SJohn Marino 	    const_rhs = XEXP (tem, 0);
1591e4b17023SJohn Marino 	}
1592e4b17023SJohn Marino       if (const_rhs == NULL_RTX && REG_P (rhs))
1593e4b17023SJohn Marino 	{
1594e4b17023SJohn Marino 	  rtx tem = cselib_expand_value_rtx (rhs, scratch, 5);
1595e4b17023SJohn Marino 
1596e4b17023SJohn Marino 	  if (tem && CONSTANT_P (tem))
1597e4b17023SJohn Marino 	    const_rhs = tem;
1598e4b17023SJohn Marino 	}
1599e4b17023SJohn Marino     }
1600e4b17023SJohn Marino 
1601e4b17023SJohn Marino   /* Check to see if this stores causes some other stores to be
1602e4b17023SJohn Marino      dead.  */
1603e4b17023SJohn Marino   ptr = active_local_stores;
1604e4b17023SJohn Marino   last = NULL;
1605e4b17023SJohn Marino   redundant_reason = NULL;
1606e4b17023SJohn Marino   mem = canon_rtx (mem);
1607e4b17023SJohn Marino   /* For alias_set != 0 canon_true_dependence should be never called.  */
1608e4b17023SJohn Marino   if (spill_alias_set)
1609e4b17023SJohn Marino     mem_addr = NULL_RTX;
1610e4b17023SJohn Marino   else
1611e4b17023SJohn Marino     {
1612e4b17023SJohn Marino       if (group_id < 0)
1613e4b17023SJohn Marino 	mem_addr = base->val_rtx;
1614e4b17023SJohn Marino       else
1615e4b17023SJohn Marino 	{
1616e4b17023SJohn Marino 	  group_info_t group
1617e4b17023SJohn Marino 	    = VEC_index (group_info_t, rtx_group_vec, group_id);
1618e4b17023SJohn Marino 	  mem_addr = group->canon_base_addr;
1619e4b17023SJohn Marino 	}
1620e4b17023SJohn Marino       if (offset)
1621e4b17023SJohn Marino 	mem_addr = plus_constant (mem_addr, offset);
1622e4b17023SJohn Marino     }
1623e4b17023SJohn Marino 
1624e4b17023SJohn Marino   while (ptr)
1625e4b17023SJohn Marino     {
1626e4b17023SJohn Marino       insn_info_t next = ptr->next_local_store;
1627e4b17023SJohn Marino       store_info_t s_info = ptr->store_rec;
1628e4b17023SJohn Marino       bool del = true;
1629e4b17023SJohn Marino 
1630e4b17023SJohn Marino       /* Skip the clobbers. We delete the active insn if this insn
1631e4b17023SJohn Marino 	 shadows the set.  To have been put on the active list, it
1632e4b17023SJohn Marino 	 has exactly on set. */
1633e4b17023SJohn Marino       while (!s_info->is_set)
1634e4b17023SJohn Marino 	s_info = s_info->next;
1635e4b17023SJohn Marino 
1636e4b17023SJohn Marino       if (s_info->alias_set != spill_alias_set)
1637e4b17023SJohn Marino 	del = false;
1638e4b17023SJohn Marino       else if (s_info->alias_set)
1639e4b17023SJohn Marino 	{
1640e4b17023SJohn Marino 	  struct clear_alias_mode_holder *entry
1641e4b17023SJohn Marino 	    = clear_alias_set_lookup (s_info->alias_set);
1642e4b17023SJohn Marino 	  /* Generally, spills cannot be processed if and of the
1643e4b17023SJohn Marino 	     references to the slot have a different mode.  But if
1644e4b17023SJohn Marino 	     we are in the same block and mode is exactly the same
1645e4b17023SJohn Marino 	     between this store and one before in the same block,
1646e4b17023SJohn Marino 	     we can still delete it.  */
1647e4b17023SJohn Marino 	  if ((GET_MODE (mem) == GET_MODE (s_info->mem))
1648e4b17023SJohn Marino 	      && (GET_MODE (mem) == entry->mode))
1649e4b17023SJohn Marino 	    {
1650e4b17023SJohn Marino 	      del = true;
1651e4b17023SJohn Marino 	      set_all_positions_unneeded (s_info);
1652e4b17023SJohn Marino 	    }
1653e4b17023SJohn Marino 	  if (dump_file)
1654e4b17023SJohn Marino 	    fprintf (dump_file, "    trying spill store in insn=%d alias_set=%d\n",
1655e4b17023SJohn Marino 		     INSN_UID (ptr->insn), (int) s_info->alias_set);
1656e4b17023SJohn Marino 	}
1657e4b17023SJohn Marino       else if ((s_info->group_id == group_id)
1658e4b17023SJohn Marino 	       && (s_info->cse_base == base))
1659e4b17023SJohn Marino 	{
1660e4b17023SJohn Marino 	  HOST_WIDE_INT i;
1661e4b17023SJohn Marino 	  if (dump_file)
1662e4b17023SJohn Marino 	    fprintf (dump_file, "    trying store in insn=%d gid=%d[%d..%d)\n",
1663e4b17023SJohn Marino 		     INSN_UID (ptr->insn), s_info->group_id,
1664e4b17023SJohn Marino 		     (int)s_info->begin, (int)s_info->end);
1665e4b17023SJohn Marino 
1666e4b17023SJohn Marino 	  /* Even if PTR won't be eliminated as unneeded, if both
1667e4b17023SJohn Marino 	     PTR and this insn store the same constant value, we might
1668e4b17023SJohn Marino 	     eliminate this insn instead.  */
1669e4b17023SJohn Marino 	  if (s_info->const_rhs
1670e4b17023SJohn Marino 	      && const_rhs
1671e4b17023SJohn Marino 	      && offset >= s_info->begin
1672e4b17023SJohn Marino 	      && offset + width <= s_info->end
1673e4b17023SJohn Marino 	      && all_positions_needed_p (s_info, offset - s_info->begin,
1674e4b17023SJohn Marino 					 width))
1675e4b17023SJohn Marino 	    {
1676e4b17023SJohn Marino 	      if (GET_MODE (mem) == BLKmode)
1677e4b17023SJohn Marino 		{
1678e4b17023SJohn Marino 		  if (GET_MODE (s_info->mem) == BLKmode
1679e4b17023SJohn Marino 		      && s_info->const_rhs == const_rhs)
1680e4b17023SJohn Marino 		    redundant_reason = ptr;
1681e4b17023SJohn Marino 		}
1682e4b17023SJohn Marino 	      else if (s_info->const_rhs == const0_rtx
1683e4b17023SJohn Marino 		       && const_rhs == const0_rtx)
1684e4b17023SJohn Marino 		redundant_reason = ptr;
1685e4b17023SJohn Marino 	      else
1686e4b17023SJohn Marino 		{
1687e4b17023SJohn Marino 		  rtx val;
1688e4b17023SJohn Marino 		  start_sequence ();
1689e4b17023SJohn Marino 		  val = get_stored_val (s_info, GET_MODE (mem),
1690e4b17023SJohn Marino 					offset, offset + width,
1691e4b17023SJohn Marino 					BLOCK_FOR_INSN (insn_info->insn),
1692e4b17023SJohn Marino 					true);
1693e4b17023SJohn Marino 		  if (get_insns () != NULL)
1694e4b17023SJohn Marino 		    val = NULL_RTX;
1695e4b17023SJohn Marino 		  end_sequence ();
1696e4b17023SJohn Marino 		  if (val && rtx_equal_p (val, const_rhs))
1697e4b17023SJohn Marino 		    redundant_reason = ptr;
1698e4b17023SJohn Marino 		}
1699e4b17023SJohn Marino 	    }
1700e4b17023SJohn Marino 
1701e4b17023SJohn Marino 	  for (i = MAX (offset, s_info->begin);
1702e4b17023SJohn Marino 	       i < offset + width && i < s_info->end;
1703e4b17023SJohn Marino 	       i++)
1704e4b17023SJohn Marino 	    set_position_unneeded (s_info, i - s_info->begin);
1705e4b17023SJohn Marino 	}
1706e4b17023SJohn Marino       else if (s_info->rhs)
1707e4b17023SJohn Marino 	/* Need to see if it is possible for this store to overwrite
1708e4b17023SJohn Marino 	   the value of store_info.  If it is, set the rhs to NULL to
1709e4b17023SJohn Marino 	   keep it from being used to remove a load.  */
1710e4b17023SJohn Marino 	{
1711e4b17023SJohn Marino 	  if (canon_true_dependence (s_info->mem,
1712e4b17023SJohn Marino 				     GET_MODE (s_info->mem),
1713e4b17023SJohn Marino 				     s_info->mem_addr,
1714e4b17023SJohn Marino 				     mem, mem_addr))
1715e4b17023SJohn Marino 	    {
1716e4b17023SJohn Marino 	      s_info->rhs = NULL;
1717e4b17023SJohn Marino 	      s_info->const_rhs = NULL;
1718e4b17023SJohn Marino 	    }
1719e4b17023SJohn Marino 	}
1720e4b17023SJohn Marino 
1721e4b17023SJohn Marino       /* An insn can be deleted if every position of every one of
1722e4b17023SJohn Marino 	 its s_infos is zero.  */
1723e4b17023SJohn Marino       if (any_positions_needed_p (s_info))
1724e4b17023SJohn Marino 	del = false;
1725e4b17023SJohn Marino 
1726e4b17023SJohn Marino       if (del)
1727e4b17023SJohn Marino 	{
1728e4b17023SJohn Marino 	  insn_info_t insn_to_delete = ptr;
1729e4b17023SJohn Marino 
1730e4b17023SJohn Marino 	  active_local_stores_len--;
1731e4b17023SJohn Marino 	  if (last)
1732e4b17023SJohn Marino 	    last->next_local_store = ptr->next_local_store;
1733e4b17023SJohn Marino 	  else
1734e4b17023SJohn Marino 	    active_local_stores = ptr->next_local_store;
1735e4b17023SJohn Marino 
1736e4b17023SJohn Marino 	  if (!insn_to_delete->cannot_delete)
1737e4b17023SJohn Marino 	    delete_dead_store_insn (insn_to_delete);
1738e4b17023SJohn Marino 	}
1739e4b17023SJohn Marino       else
1740e4b17023SJohn Marino 	last = ptr;
1741e4b17023SJohn Marino 
1742e4b17023SJohn Marino       ptr = next;
1743e4b17023SJohn Marino     }
1744e4b17023SJohn Marino 
1745e4b17023SJohn Marino   /* Finish filling in the store_info.  */
1746e4b17023SJohn Marino   store_info->next = insn_info->store_rec;
1747e4b17023SJohn Marino   insn_info->store_rec = store_info;
1748e4b17023SJohn Marino   store_info->mem = mem;
1749e4b17023SJohn Marino   store_info->alias_set = spill_alias_set;
1750e4b17023SJohn Marino   store_info->mem_addr = mem_addr;
1751e4b17023SJohn Marino   store_info->cse_base = base;
1752e4b17023SJohn Marino   if (width > HOST_BITS_PER_WIDE_INT)
1753e4b17023SJohn Marino     {
1754e4b17023SJohn Marino       store_info->is_large = true;
1755e4b17023SJohn Marino       store_info->positions_needed.large.count = 0;
1756e4b17023SJohn Marino       store_info->positions_needed.large.bmap = BITMAP_ALLOC (NULL);
1757e4b17023SJohn Marino     }
1758e4b17023SJohn Marino   else
1759e4b17023SJohn Marino     {
1760e4b17023SJohn Marino       store_info->is_large = false;
1761e4b17023SJohn Marino       store_info->positions_needed.small_bitmask = lowpart_bitmask (width);
1762e4b17023SJohn Marino     }
1763e4b17023SJohn Marino   store_info->group_id = group_id;
1764e4b17023SJohn Marino   store_info->begin = offset;
1765e4b17023SJohn Marino   store_info->end = offset + width;
1766e4b17023SJohn Marino   store_info->is_set = GET_CODE (body) == SET;
1767e4b17023SJohn Marino   store_info->rhs = rhs;
1768e4b17023SJohn Marino   store_info->const_rhs = const_rhs;
1769e4b17023SJohn Marino   store_info->redundant_reason = redundant_reason;
1770e4b17023SJohn Marino 
1771e4b17023SJohn Marino   /* If this is a clobber, we return 0.  We will only be able to
1772e4b17023SJohn Marino      delete this insn if there is only one store USED store, but we
1773e4b17023SJohn Marino      can use the clobber to delete other stores earlier.  */
1774e4b17023SJohn Marino   return store_info->is_set ? 1 : 0;
1775e4b17023SJohn Marino }
1776e4b17023SJohn Marino 
1777e4b17023SJohn Marino 
1778e4b17023SJohn Marino static void
dump_insn_info(const char * start,insn_info_t insn_info)1779e4b17023SJohn Marino dump_insn_info (const char * start, insn_info_t insn_info)
1780e4b17023SJohn Marino {
1781e4b17023SJohn Marino   fprintf (dump_file, "%s insn=%d %s\n", start,
1782e4b17023SJohn Marino 	   INSN_UID (insn_info->insn),
1783e4b17023SJohn Marino 	   insn_info->store_rec ? "has store" : "naked");
1784e4b17023SJohn Marino }
1785e4b17023SJohn Marino 
1786e4b17023SJohn Marino 
1787e4b17023SJohn Marino /* If the modes are different and the value's source and target do not
1788e4b17023SJohn Marino    line up, we need to extract the value from lower part of the rhs of
1789e4b17023SJohn Marino    the store, shift it, and then put it into a form that can be shoved
1790e4b17023SJohn Marino    into the read_insn.  This function generates a right SHIFT of a
1791e4b17023SJohn Marino    value that is at least ACCESS_SIZE bytes wide of READ_MODE.  The
1792e4b17023SJohn Marino    shift sequence is returned or NULL if we failed to find a
1793e4b17023SJohn Marino    shift.  */
1794e4b17023SJohn Marino 
1795e4b17023SJohn Marino static rtx
find_shift_sequence(int access_size,store_info_t store_info,enum machine_mode read_mode,int shift,bool speed,bool require_cst)1796e4b17023SJohn Marino find_shift_sequence (int access_size,
1797e4b17023SJohn Marino 		     store_info_t store_info,
1798e4b17023SJohn Marino 		     enum machine_mode read_mode,
1799e4b17023SJohn Marino 		     int shift, bool speed, bool require_cst)
1800e4b17023SJohn Marino {
1801e4b17023SJohn Marino   enum machine_mode store_mode = GET_MODE (store_info->mem);
1802e4b17023SJohn Marino   enum machine_mode new_mode;
1803e4b17023SJohn Marino   rtx read_reg = NULL;
1804e4b17023SJohn Marino 
1805e4b17023SJohn Marino   /* Some machines like the x86 have shift insns for each size of
1806e4b17023SJohn Marino      operand.  Other machines like the ppc or the ia-64 may only have
1807e4b17023SJohn Marino      shift insns that shift values within 32 or 64 bit registers.
1808e4b17023SJohn Marino      This loop tries to find the smallest shift insn that will right
1809e4b17023SJohn Marino      justify the value we want to read but is available in one insn on
1810e4b17023SJohn Marino      the machine.  */
1811e4b17023SJohn Marino 
1812e4b17023SJohn Marino   for (new_mode = smallest_mode_for_size (access_size * BITS_PER_UNIT,
1813e4b17023SJohn Marino 					  MODE_INT);
1814e4b17023SJohn Marino        GET_MODE_BITSIZE (new_mode) <= BITS_PER_WORD;
1815e4b17023SJohn Marino        new_mode = GET_MODE_WIDER_MODE (new_mode))
1816e4b17023SJohn Marino     {
1817e4b17023SJohn Marino       rtx target, new_reg, shift_seq, insn, new_lhs;
1818e4b17023SJohn Marino       int cost;
1819e4b17023SJohn Marino 
1820e4b17023SJohn Marino       /* If a constant was stored into memory, try to simplify it here,
1821e4b17023SJohn Marino 	 otherwise the cost of the shift might preclude this optimization
1822e4b17023SJohn Marino 	 e.g. at -Os, even when no actual shift will be needed.  */
1823e4b17023SJohn Marino       if (store_info->const_rhs)
1824e4b17023SJohn Marino 	{
1825e4b17023SJohn Marino 	  unsigned int byte = subreg_lowpart_offset (new_mode, store_mode);
1826e4b17023SJohn Marino 	  rtx ret = simplify_subreg (new_mode, store_info->const_rhs,
1827e4b17023SJohn Marino 				     store_mode, byte);
1828e4b17023SJohn Marino 	  if (ret && CONSTANT_P (ret))
1829e4b17023SJohn Marino 	    {
1830e4b17023SJohn Marino 	      ret = simplify_const_binary_operation (LSHIFTRT, new_mode,
1831e4b17023SJohn Marino 						     ret, GEN_INT (shift));
1832e4b17023SJohn Marino 	      if (ret && CONSTANT_P (ret))
1833e4b17023SJohn Marino 		{
1834e4b17023SJohn Marino 		  byte = subreg_lowpart_offset (read_mode, new_mode);
1835e4b17023SJohn Marino 		  ret = simplify_subreg (read_mode, ret, new_mode, byte);
1836e4b17023SJohn Marino 		  if (ret && CONSTANT_P (ret)
1837e4b17023SJohn Marino 		      && set_src_cost (ret, speed) <= COSTS_N_INSNS (1))
1838e4b17023SJohn Marino 		    return ret;
1839e4b17023SJohn Marino 		}
1840e4b17023SJohn Marino 	    }
1841e4b17023SJohn Marino 	}
1842e4b17023SJohn Marino 
1843e4b17023SJohn Marino       if (require_cst)
1844e4b17023SJohn Marino 	return NULL_RTX;
1845e4b17023SJohn Marino 
1846e4b17023SJohn Marino       /* Try a wider mode if truncating the store mode to NEW_MODE
1847e4b17023SJohn Marino 	 requires a real instruction.  */
1848e4b17023SJohn Marino       if (GET_MODE_BITSIZE (new_mode) < GET_MODE_BITSIZE (store_mode)
1849e4b17023SJohn Marino 	  && !TRULY_NOOP_TRUNCATION_MODES_P (new_mode, store_mode))
1850e4b17023SJohn Marino 	continue;
1851e4b17023SJohn Marino 
1852e4b17023SJohn Marino       /* Also try a wider mode if the necessary punning is either not
1853e4b17023SJohn Marino 	 desirable or not possible.  */
1854e4b17023SJohn Marino       if (!CONSTANT_P (store_info->rhs)
1855e4b17023SJohn Marino 	  && !MODES_TIEABLE_P (new_mode, store_mode))
1856e4b17023SJohn Marino 	continue;
1857e4b17023SJohn Marino 
1858e4b17023SJohn Marino       new_reg = gen_reg_rtx (new_mode);
1859e4b17023SJohn Marino 
1860e4b17023SJohn Marino       start_sequence ();
1861e4b17023SJohn Marino 
1862e4b17023SJohn Marino       /* In theory we could also check for an ashr.  Ian Taylor knows
1863e4b17023SJohn Marino 	 of one dsp where the cost of these two was not the same.  But
1864e4b17023SJohn Marino 	 this really is a rare case anyway.  */
1865e4b17023SJohn Marino       target = expand_binop (new_mode, lshr_optab, new_reg,
1866e4b17023SJohn Marino 			     GEN_INT (shift), new_reg, 1, OPTAB_DIRECT);
1867e4b17023SJohn Marino 
1868e4b17023SJohn Marino       shift_seq = get_insns ();
1869e4b17023SJohn Marino       end_sequence ();
1870e4b17023SJohn Marino 
1871e4b17023SJohn Marino       if (target != new_reg || shift_seq == NULL)
1872e4b17023SJohn Marino 	continue;
1873e4b17023SJohn Marino 
1874e4b17023SJohn Marino       cost = 0;
1875e4b17023SJohn Marino       for (insn = shift_seq; insn != NULL_RTX; insn = NEXT_INSN (insn))
1876e4b17023SJohn Marino 	if (INSN_P (insn))
1877e4b17023SJohn Marino 	  cost += insn_rtx_cost (PATTERN (insn), speed);
1878e4b17023SJohn Marino 
1879e4b17023SJohn Marino       /* The computation up to here is essentially independent
1880e4b17023SJohn Marino 	 of the arguments and could be precomputed.  It may
1881e4b17023SJohn Marino 	 not be worth doing so.  We could precompute if
1882e4b17023SJohn Marino 	 worthwhile or at least cache the results.  The result
1883e4b17023SJohn Marino 	 technically depends on both SHIFT and ACCESS_SIZE,
1884e4b17023SJohn Marino 	 but in practice the answer will depend only on ACCESS_SIZE.  */
1885e4b17023SJohn Marino 
1886e4b17023SJohn Marino       if (cost > COSTS_N_INSNS (1))
1887e4b17023SJohn Marino 	continue;
1888e4b17023SJohn Marino 
1889e4b17023SJohn Marino       new_lhs = extract_low_bits (new_mode, store_mode,
1890e4b17023SJohn Marino 				  copy_rtx (store_info->rhs));
1891e4b17023SJohn Marino       if (new_lhs == NULL_RTX)
1892e4b17023SJohn Marino 	continue;
1893e4b17023SJohn Marino 
1894e4b17023SJohn Marino       /* We found an acceptable shift.  Generate a move to
1895e4b17023SJohn Marino 	 take the value from the store and put it into the
1896e4b17023SJohn Marino 	 shift pseudo, then shift it, then generate another
1897e4b17023SJohn Marino 	 move to put in into the target of the read.  */
1898e4b17023SJohn Marino       emit_move_insn (new_reg, new_lhs);
1899e4b17023SJohn Marino       emit_insn (shift_seq);
1900e4b17023SJohn Marino       read_reg = extract_low_bits (read_mode, new_mode, new_reg);
1901e4b17023SJohn Marino       break;
1902e4b17023SJohn Marino     }
1903e4b17023SJohn Marino 
1904e4b17023SJohn Marino   return read_reg;
1905e4b17023SJohn Marino }
1906e4b17023SJohn Marino 
1907e4b17023SJohn Marino 
1908e4b17023SJohn Marino /* Call back for note_stores to find the hard regs set or clobbered by
1909e4b17023SJohn Marino    insn.  Data is a bitmap of the hardregs set so far.  */
1910e4b17023SJohn Marino 
1911e4b17023SJohn Marino static void
look_for_hardregs(rtx x,const_rtx pat ATTRIBUTE_UNUSED,void * data)1912e4b17023SJohn Marino look_for_hardregs (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data)
1913e4b17023SJohn Marino {
1914e4b17023SJohn Marino   bitmap regs_set = (bitmap) data;
1915e4b17023SJohn Marino 
1916e4b17023SJohn Marino   if (REG_P (x)
1917e4b17023SJohn Marino       && HARD_REGISTER_P (x))
1918e4b17023SJohn Marino     {
1919e4b17023SJohn Marino       unsigned int regno = REGNO (x);
1920e4b17023SJohn Marino       bitmap_set_range (regs_set, regno,
1921e4b17023SJohn Marino 			hard_regno_nregs[regno][GET_MODE (x)]);
1922e4b17023SJohn Marino     }
1923e4b17023SJohn Marino }
1924e4b17023SJohn Marino 
1925e4b17023SJohn Marino /* Helper function for replace_read and record_store.
1926e4b17023SJohn Marino    Attempt to return a value stored in STORE_INFO, from READ_BEGIN
1927e4b17023SJohn Marino    to one before READ_END bytes read in READ_MODE.  Return NULL
1928e4b17023SJohn Marino    if not successful.  If REQUIRE_CST is true, return always constant.  */
1929e4b17023SJohn Marino 
1930e4b17023SJohn Marino static rtx
get_stored_val(store_info_t store_info,enum machine_mode read_mode,HOST_WIDE_INT read_begin,HOST_WIDE_INT read_end,basic_block bb,bool require_cst)1931e4b17023SJohn Marino get_stored_val (store_info_t store_info, enum machine_mode read_mode,
1932e4b17023SJohn Marino 		HOST_WIDE_INT read_begin, HOST_WIDE_INT read_end,
1933e4b17023SJohn Marino 		basic_block bb, bool require_cst)
1934e4b17023SJohn Marino {
1935e4b17023SJohn Marino   enum machine_mode store_mode = GET_MODE (store_info->mem);
1936e4b17023SJohn Marino   int shift;
1937e4b17023SJohn Marino   int access_size; /* In bytes.  */
1938e4b17023SJohn Marino   rtx read_reg;
1939e4b17023SJohn Marino 
1940e4b17023SJohn Marino   /* To get here the read is within the boundaries of the write so
1941e4b17023SJohn Marino      shift will never be negative.  Start out with the shift being in
1942e4b17023SJohn Marino      bytes.  */
1943e4b17023SJohn Marino   if (store_mode == BLKmode)
1944e4b17023SJohn Marino     shift = 0;
1945e4b17023SJohn Marino   else if (BYTES_BIG_ENDIAN)
1946e4b17023SJohn Marino     shift = store_info->end - read_end;
1947e4b17023SJohn Marino   else
1948e4b17023SJohn Marino     shift = read_begin - store_info->begin;
1949e4b17023SJohn Marino 
1950e4b17023SJohn Marino   access_size = shift + GET_MODE_SIZE (read_mode);
1951e4b17023SJohn Marino 
1952e4b17023SJohn Marino   /* From now on it is bits.  */
1953e4b17023SJohn Marino   shift *= BITS_PER_UNIT;
1954e4b17023SJohn Marino 
1955e4b17023SJohn Marino   if (shift)
1956e4b17023SJohn Marino     read_reg = find_shift_sequence (access_size, store_info, read_mode, shift,
1957e4b17023SJohn Marino     				    optimize_bb_for_speed_p (bb),
1958e4b17023SJohn Marino 				    require_cst);
1959e4b17023SJohn Marino   else if (store_mode == BLKmode)
1960e4b17023SJohn Marino     {
1961e4b17023SJohn Marino       /* The store is a memset (addr, const_val, const_size).  */
1962e4b17023SJohn Marino       gcc_assert (CONST_INT_P (store_info->rhs));
1963e4b17023SJohn Marino       store_mode = int_mode_for_mode (read_mode);
1964e4b17023SJohn Marino       if (store_mode == BLKmode)
1965e4b17023SJohn Marino 	read_reg = NULL_RTX;
1966e4b17023SJohn Marino       else if (store_info->rhs == const0_rtx)
1967e4b17023SJohn Marino 	read_reg = extract_low_bits (read_mode, store_mode, const0_rtx);
1968e4b17023SJohn Marino       else if (GET_MODE_BITSIZE (store_mode) > HOST_BITS_PER_WIDE_INT
1969e4b17023SJohn Marino 	       || BITS_PER_UNIT >= HOST_BITS_PER_WIDE_INT)
1970e4b17023SJohn Marino 	read_reg = NULL_RTX;
1971e4b17023SJohn Marino       else
1972e4b17023SJohn Marino 	{
1973e4b17023SJohn Marino 	  unsigned HOST_WIDE_INT c
1974e4b17023SJohn Marino 	    = INTVAL (store_info->rhs)
1975e4b17023SJohn Marino 	      & (((HOST_WIDE_INT) 1 << BITS_PER_UNIT) - 1);
1976e4b17023SJohn Marino 	  int shift = BITS_PER_UNIT;
1977e4b17023SJohn Marino 	  while (shift < HOST_BITS_PER_WIDE_INT)
1978e4b17023SJohn Marino 	    {
1979e4b17023SJohn Marino 	      c |= (c << shift);
1980e4b17023SJohn Marino 	      shift <<= 1;
1981e4b17023SJohn Marino 	    }
1982e4b17023SJohn Marino 	  read_reg = gen_int_mode (c, store_mode);
1983e4b17023SJohn Marino 	  read_reg = extract_low_bits (read_mode, store_mode, read_reg);
1984e4b17023SJohn Marino 	}
1985e4b17023SJohn Marino     }
1986e4b17023SJohn Marino   else if (store_info->const_rhs
1987e4b17023SJohn Marino 	   && (require_cst
1988e4b17023SJohn Marino 	       || GET_MODE_CLASS (read_mode) != GET_MODE_CLASS (store_mode)))
1989e4b17023SJohn Marino     read_reg = extract_low_bits (read_mode, store_mode,
1990e4b17023SJohn Marino 				 copy_rtx (store_info->const_rhs));
1991e4b17023SJohn Marino   else
1992e4b17023SJohn Marino     read_reg = extract_low_bits (read_mode, store_mode,
1993e4b17023SJohn Marino 				 copy_rtx (store_info->rhs));
1994e4b17023SJohn Marino   if (require_cst && read_reg && !CONSTANT_P (read_reg))
1995e4b17023SJohn Marino     read_reg = NULL_RTX;
1996e4b17023SJohn Marino   return read_reg;
1997e4b17023SJohn Marino }
1998e4b17023SJohn Marino 
1999e4b17023SJohn Marino /* Take a sequence of:
2000e4b17023SJohn Marino      A <- r1
2001e4b17023SJohn Marino      ...
2002e4b17023SJohn Marino      ... <- A
2003e4b17023SJohn Marino 
2004e4b17023SJohn Marino    and change it into
2005e4b17023SJohn Marino    r2 <- r1
2006e4b17023SJohn Marino    A <- r1
2007e4b17023SJohn Marino    ...
2008e4b17023SJohn Marino    ... <- r2
2009e4b17023SJohn Marino 
2010e4b17023SJohn Marino    or
2011e4b17023SJohn Marino 
2012e4b17023SJohn Marino    r3 <- extract (r1)
2013e4b17023SJohn Marino    r3 <- r3 >> shift
2014e4b17023SJohn Marino    r2 <- extract (r3)
2015e4b17023SJohn Marino    ... <- r2
2016e4b17023SJohn Marino 
2017e4b17023SJohn Marino    or
2018e4b17023SJohn Marino 
2019e4b17023SJohn Marino    r2 <- extract (r1)
2020e4b17023SJohn Marino    ... <- r2
2021e4b17023SJohn Marino 
2022e4b17023SJohn Marino    Depending on the alignment and the mode of the store and
2023e4b17023SJohn Marino    subsequent load.
2024e4b17023SJohn Marino 
2025e4b17023SJohn Marino 
2026e4b17023SJohn Marino    The STORE_INFO and STORE_INSN are for the store and READ_INFO
2027e4b17023SJohn Marino    and READ_INSN are for the read.  Return true if the replacement
2028e4b17023SJohn Marino    went ok.  */
2029e4b17023SJohn Marino 
2030e4b17023SJohn Marino static bool
replace_read(store_info_t store_info,insn_info_t store_insn,read_info_t read_info,insn_info_t read_insn,rtx * loc,bitmap regs_live)2031e4b17023SJohn Marino replace_read (store_info_t store_info, insn_info_t store_insn,
2032e4b17023SJohn Marino 	      read_info_t read_info, insn_info_t read_insn, rtx *loc,
2033e4b17023SJohn Marino 	      bitmap regs_live)
2034e4b17023SJohn Marino {
2035e4b17023SJohn Marino   enum machine_mode store_mode = GET_MODE (store_info->mem);
2036e4b17023SJohn Marino   enum machine_mode read_mode = GET_MODE (read_info->mem);
2037e4b17023SJohn Marino   rtx insns, this_insn, read_reg;
2038e4b17023SJohn Marino   basic_block bb;
2039e4b17023SJohn Marino 
2040e4b17023SJohn Marino   if (!dbg_cnt (dse))
2041e4b17023SJohn Marino     return false;
2042e4b17023SJohn Marino 
2043e4b17023SJohn Marino   /* Create a sequence of instructions to set up the read register.
2044e4b17023SJohn Marino      This sequence goes immediately before the store and its result
2045e4b17023SJohn Marino      is read by the load.
2046e4b17023SJohn Marino 
2047e4b17023SJohn Marino      We need to keep this in perspective.  We are replacing a read
2048e4b17023SJohn Marino      with a sequence of insns, but the read will almost certainly be
2049e4b17023SJohn Marino      in cache, so it is not going to be an expensive one.  Thus, we
2050e4b17023SJohn Marino      are not willing to do a multi insn shift or worse a subroutine
2051e4b17023SJohn Marino      call to get rid of the read.  */
2052e4b17023SJohn Marino   if (dump_file)
2053e4b17023SJohn Marino     fprintf (dump_file, "trying to replace %smode load in insn %d"
2054e4b17023SJohn Marino 	     " from %smode store in insn %d\n",
2055e4b17023SJohn Marino 	     GET_MODE_NAME (read_mode), INSN_UID (read_insn->insn),
2056e4b17023SJohn Marino 	     GET_MODE_NAME (store_mode), INSN_UID (store_insn->insn));
2057e4b17023SJohn Marino   start_sequence ();
2058e4b17023SJohn Marino   bb = BLOCK_FOR_INSN (read_insn->insn);
2059e4b17023SJohn Marino   read_reg = get_stored_val (store_info,
2060e4b17023SJohn Marino 			     read_mode, read_info->begin, read_info->end,
2061e4b17023SJohn Marino 			     bb, false);
2062e4b17023SJohn Marino   if (read_reg == NULL_RTX)
2063e4b17023SJohn Marino     {
2064e4b17023SJohn Marino       end_sequence ();
2065e4b17023SJohn Marino       if (dump_file)
2066e4b17023SJohn Marino 	fprintf (dump_file, " -- could not extract bits of stored value\n");
2067e4b17023SJohn Marino       return false;
2068e4b17023SJohn Marino     }
2069e4b17023SJohn Marino   /* Force the value into a new register so that it won't be clobbered
2070e4b17023SJohn Marino      between the store and the load.  */
2071e4b17023SJohn Marino   read_reg = copy_to_mode_reg (read_mode, read_reg);
2072e4b17023SJohn Marino   insns = get_insns ();
2073e4b17023SJohn Marino   end_sequence ();
2074e4b17023SJohn Marino 
2075e4b17023SJohn Marino   if (insns != NULL_RTX)
2076e4b17023SJohn Marino     {
2077e4b17023SJohn Marino       /* Now we have to scan the set of new instructions to see if the
2078e4b17023SJohn Marino 	 sequence contains and sets of hardregs that happened to be
2079e4b17023SJohn Marino 	 live at this point.  For instance, this can happen if one of
2080e4b17023SJohn Marino 	 the insns sets the CC and the CC happened to be live at that
2081e4b17023SJohn Marino 	 point.  This does occasionally happen, see PR 37922.  */
2082e4b17023SJohn Marino       bitmap regs_set = BITMAP_ALLOC (NULL);
2083e4b17023SJohn Marino 
2084e4b17023SJohn Marino       for (this_insn = insns; this_insn != NULL_RTX; this_insn = NEXT_INSN (this_insn))
2085e4b17023SJohn Marino 	note_stores (PATTERN (this_insn), look_for_hardregs, regs_set);
2086e4b17023SJohn Marino 
2087e4b17023SJohn Marino       bitmap_and_into (regs_set, regs_live);
2088e4b17023SJohn Marino       if (!bitmap_empty_p (regs_set))
2089e4b17023SJohn Marino 	{
2090e4b17023SJohn Marino 	  if (dump_file)
2091e4b17023SJohn Marino 	    {
2092e4b17023SJohn Marino 	      fprintf (dump_file,
2093e4b17023SJohn Marino 		       "abandoning replacement because sequence clobbers live hardregs:");
2094e4b17023SJohn Marino 	      df_print_regset (dump_file, regs_set);
2095e4b17023SJohn Marino 	    }
2096e4b17023SJohn Marino 
2097e4b17023SJohn Marino 	  BITMAP_FREE (regs_set);
2098e4b17023SJohn Marino 	  return false;
2099e4b17023SJohn Marino 	}
2100e4b17023SJohn Marino       BITMAP_FREE (regs_set);
2101e4b17023SJohn Marino     }
2102e4b17023SJohn Marino 
2103e4b17023SJohn Marino   if (validate_change (read_insn->insn, loc, read_reg, 0))
2104e4b17023SJohn Marino     {
2105e4b17023SJohn Marino       deferred_change_t deferred_change =
2106e4b17023SJohn Marino 	(deferred_change_t) pool_alloc (deferred_change_pool);
2107e4b17023SJohn Marino 
2108e4b17023SJohn Marino       /* Insert this right before the store insn where it will be safe
2109e4b17023SJohn Marino 	 from later insns that might change it before the read.  */
2110e4b17023SJohn Marino       emit_insn_before (insns, store_insn->insn);
2111e4b17023SJohn Marino 
2112e4b17023SJohn Marino       /* And now for the kludge part: cselib croaks if you just
2113e4b17023SJohn Marino 	 return at this point.  There are two reasons for this:
2114e4b17023SJohn Marino 
2115e4b17023SJohn Marino 	 1) Cselib has an idea of how many pseudos there are and
2116e4b17023SJohn Marino 	 that does not include the new ones we just added.
2117e4b17023SJohn Marino 
2118e4b17023SJohn Marino 	 2) Cselib does not know about the move insn we added
2119e4b17023SJohn Marino 	 above the store_info, and there is no way to tell it
2120e4b17023SJohn Marino 	 about it, because it has "moved on".
2121e4b17023SJohn Marino 
2122e4b17023SJohn Marino 	 Problem (1) is fixable with a certain amount of engineering.
2123e4b17023SJohn Marino 	 Problem (2) is requires starting the bb from scratch.  This
2124e4b17023SJohn Marino 	 could be expensive.
2125e4b17023SJohn Marino 
2126e4b17023SJohn Marino 	 So we are just going to have to lie.  The move/extraction
2127e4b17023SJohn Marino 	 insns are not really an issue, cselib did not see them.  But
2128e4b17023SJohn Marino 	 the use of the new pseudo read_insn is a real problem because
2129e4b17023SJohn Marino 	 cselib has not scanned this insn.  The way that we solve this
2130e4b17023SJohn Marino 	 problem is that we are just going to put the mem back for now
2131e4b17023SJohn Marino 	 and when we are finished with the block, we undo this.  We
2132e4b17023SJohn Marino 	 keep a table of mems to get rid of.  At the end of the basic
2133e4b17023SJohn Marino 	 block we can put them back.  */
2134e4b17023SJohn Marino 
2135e4b17023SJohn Marino       *loc = read_info->mem;
2136e4b17023SJohn Marino       deferred_change->next = deferred_change_list;
2137e4b17023SJohn Marino       deferred_change_list = deferred_change;
2138e4b17023SJohn Marino       deferred_change->loc = loc;
2139e4b17023SJohn Marino       deferred_change->reg = read_reg;
2140e4b17023SJohn Marino 
2141e4b17023SJohn Marino       /* Get rid of the read_info, from the point of view of the
2142e4b17023SJohn Marino 	 rest of dse, play like this read never happened.  */
2143e4b17023SJohn Marino       read_insn->read_rec = read_info->next;
2144e4b17023SJohn Marino       pool_free (read_info_pool, read_info);
2145e4b17023SJohn Marino       if (dump_file)
2146e4b17023SJohn Marino 	{
2147e4b17023SJohn Marino 	  fprintf (dump_file, " -- replaced the loaded MEM with ");
2148e4b17023SJohn Marino 	  print_simple_rtl (dump_file, read_reg);
2149e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
2150e4b17023SJohn Marino 	}
2151e4b17023SJohn Marino       return true;
2152e4b17023SJohn Marino     }
2153e4b17023SJohn Marino   else
2154e4b17023SJohn Marino     {
2155e4b17023SJohn Marino       if (dump_file)
2156e4b17023SJohn Marino 	{
2157e4b17023SJohn Marino 	  fprintf (dump_file, " -- replacing the loaded MEM with ");
2158e4b17023SJohn Marino 	  print_simple_rtl (dump_file, read_reg);
2159e4b17023SJohn Marino 	  fprintf (dump_file, " led to an invalid instruction\n");
2160e4b17023SJohn Marino 	}
2161e4b17023SJohn Marino       return false;
2162e4b17023SJohn Marino     }
2163e4b17023SJohn Marino }
2164e4b17023SJohn Marino 
2165e4b17023SJohn Marino /* A for_each_rtx callback in which DATA is the bb_info.  Check to see
2166e4b17023SJohn Marino    if LOC is a mem and if it is look at the address and kill any
2167e4b17023SJohn Marino    appropriate stores that may be active.  */
2168e4b17023SJohn Marino 
2169e4b17023SJohn Marino static int
check_mem_read_rtx(rtx * loc,void * data)2170e4b17023SJohn Marino check_mem_read_rtx (rtx *loc, void *data)
2171e4b17023SJohn Marino {
2172e4b17023SJohn Marino   rtx mem = *loc, mem_addr;
2173e4b17023SJohn Marino   bb_info_t bb_info;
2174e4b17023SJohn Marino   insn_info_t insn_info;
2175e4b17023SJohn Marino   HOST_WIDE_INT offset = 0;
2176e4b17023SJohn Marino   HOST_WIDE_INT width = 0;
2177e4b17023SJohn Marino   alias_set_type spill_alias_set = 0;
2178e4b17023SJohn Marino   cselib_val *base = NULL;
2179e4b17023SJohn Marino   int group_id;
2180e4b17023SJohn Marino   read_info_t read_info;
2181e4b17023SJohn Marino 
2182e4b17023SJohn Marino   if (!mem || !MEM_P (mem))
2183e4b17023SJohn Marino     return 0;
2184e4b17023SJohn Marino 
2185e4b17023SJohn Marino   bb_info = (bb_info_t) data;
2186e4b17023SJohn Marino   insn_info = bb_info->last_insn;
2187e4b17023SJohn Marino 
2188e4b17023SJohn Marino   if ((MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
2189e4b17023SJohn Marino       || (MEM_VOLATILE_P (mem)))
2190e4b17023SJohn Marino     {
2191e4b17023SJohn Marino       if (dump_file)
2192e4b17023SJohn Marino 	fprintf (dump_file, " adding wild read, volatile or barrier.\n");
2193e4b17023SJohn Marino       add_wild_read (bb_info);
2194e4b17023SJohn Marino       insn_info->cannot_delete = true;
2195e4b17023SJohn Marino       return 0;
2196e4b17023SJohn Marino     }
2197e4b17023SJohn Marino 
2198e4b17023SJohn Marino   /* If it is reading readonly mem, then there can be no conflict with
2199e4b17023SJohn Marino      another write. */
2200e4b17023SJohn Marino   if (MEM_READONLY_P (mem))
2201e4b17023SJohn Marino     return 0;
2202e4b17023SJohn Marino 
2203e4b17023SJohn Marino   if (!canon_address (mem, &spill_alias_set, &group_id, &offset, &base))
2204e4b17023SJohn Marino     {
2205e4b17023SJohn Marino       if (dump_file)
2206e4b17023SJohn Marino 	fprintf (dump_file, " adding wild read, canon_address failure.\n");
2207e4b17023SJohn Marino       add_wild_read (bb_info);
2208e4b17023SJohn Marino       return 0;
2209e4b17023SJohn Marino     }
2210e4b17023SJohn Marino 
2211e4b17023SJohn Marino   if (GET_MODE (mem) == BLKmode)
2212e4b17023SJohn Marino     width = -1;
2213e4b17023SJohn Marino   else
2214e4b17023SJohn Marino     width = GET_MODE_SIZE (GET_MODE (mem));
2215e4b17023SJohn Marino 
2216e4b17023SJohn Marino   read_info = (read_info_t) pool_alloc (read_info_pool);
2217e4b17023SJohn Marino   read_info->group_id = group_id;
2218e4b17023SJohn Marino   read_info->mem = mem;
2219e4b17023SJohn Marino   read_info->alias_set = spill_alias_set;
2220e4b17023SJohn Marino   read_info->begin = offset;
2221e4b17023SJohn Marino   read_info->end = offset + width;
2222e4b17023SJohn Marino   read_info->next = insn_info->read_rec;
2223e4b17023SJohn Marino   insn_info->read_rec = read_info;
2224e4b17023SJohn Marino   /* For alias_set != 0 canon_true_dependence should be never called.  */
2225e4b17023SJohn Marino   if (spill_alias_set)
2226e4b17023SJohn Marino     mem_addr = NULL_RTX;
2227e4b17023SJohn Marino   else
2228e4b17023SJohn Marino     {
2229e4b17023SJohn Marino       if (group_id < 0)
2230e4b17023SJohn Marino 	mem_addr = base->val_rtx;
2231e4b17023SJohn Marino       else
2232e4b17023SJohn Marino 	{
2233e4b17023SJohn Marino 	  group_info_t group
2234e4b17023SJohn Marino 	    = VEC_index (group_info_t, rtx_group_vec, group_id);
2235e4b17023SJohn Marino 	  mem_addr = group->canon_base_addr;
2236e4b17023SJohn Marino 	}
2237e4b17023SJohn Marino       if (offset)
2238e4b17023SJohn Marino 	mem_addr = plus_constant (mem_addr, offset);
2239e4b17023SJohn Marino     }
2240e4b17023SJohn Marino 
2241e4b17023SJohn Marino   /* We ignore the clobbers in store_info.  The is mildly aggressive,
2242e4b17023SJohn Marino      but there really should not be a clobber followed by a read.  */
2243e4b17023SJohn Marino 
2244e4b17023SJohn Marino   if (spill_alias_set)
2245e4b17023SJohn Marino     {
2246e4b17023SJohn Marino       insn_info_t i_ptr = active_local_stores;
2247e4b17023SJohn Marino       insn_info_t last = NULL;
2248e4b17023SJohn Marino 
2249e4b17023SJohn Marino       if (dump_file)
2250e4b17023SJohn Marino 	fprintf (dump_file, " processing spill load %d\n",
2251e4b17023SJohn Marino 		 (int) spill_alias_set);
2252e4b17023SJohn Marino 
2253e4b17023SJohn Marino       while (i_ptr)
2254e4b17023SJohn Marino 	{
2255e4b17023SJohn Marino 	  store_info_t store_info = i_ptr->store_rec;
2256e4b17023SJohn Marino 
2257e4b17023SJohn Marino 	  /* Skip the clobbers.  */
2258e4b17023SJohn Marino 	  while (!store_info->is_set)
2259e4b17023SJohn Marino 	    store_info = store_info->next;
2260e4b17023SJohn Marino 
2261e4b17023SJohn Marino 	  if (store_info->alias_set == spill_alias_set)
2262e4b17023SJohn Marino 	    {
2263e4b17023SJohn Marino 	      if (dump_file)
2264e4b17023SJohn Marino 		dump_insn_info ("removing from active", i_ptr);
2265e4b17023SJohn Marino 
2266e4b17023SJohn Marino 	      active_local_stores_len--;
2267e4b17023SJohn Marino 	      if (last)
2268e4b17023SJohn Marino 		last->next_local_store = i_ptr->next_local_store;
2269e4b17023SJohn Marino 	      else
2270e4b17023SJohn Marino 		active_local_stores = i_ptr->next_local_store;
2271e4b17023SJohn Marino 	    }
2272e4b17023SJohn Marino 	  else
2273e4b17023SJohn Marino 	    last = i_ptr;
2274e4b17023SJohn Marino 	  i_ptr = i_ptr->next_local_store;
2275e4b17023SJohn Marino 	}
2276e4b17023SJohn Marino     }
2277e4b17023SJohn Marino   else if (group_id >= 0)
2278e4b17023SJohn Marino     {
2279e4b17023SJohn Marino       /* This is the restricted case where the base is a constant or
2280e4b17023SJohn Marino 	 the frame pointer and offset is a constant.  */
2281e4b17023SJohn Marino       insn_info_t i_ptr = active_local_stores;
2282e4b17023SJohn Marino       insn_info_t last = NULL;
2283e4b17023SJohn Marino 
2284e4b17023SJohn Marino       if (dump_file)
2285e4b17023SJohn Marino 	{
2286e4b17023SJohn Marino 	  if (width == -1)
2287e4b17023SJohn Marino 	    fprintf (dump_file, " processing const load gid=%d[BLK]\n",
2288e4b17023SJohn Marino 		     group_id);
2289e4b17023SJohn Marino 	  else
2290e4b17023SJohn Marino 	    fprintf (dump_file, " processing const load gid=%d[%d..%d)\n",
2291e4b17023SJohn Marino 		     group_id, (int)offset, (int)(offset+width));
2292e4b17023SJohn Marino 	}
2293e4b17023SJohn Marino 
2294e4b17023SJohn Marino       while (i_ptr)
2295e4b17023SJohn Marino 	{
2296e4b17023SJohn Marino 	  bool remove = false;
2297e4b17023SJohn Marino 	  store_info_t store_info = i_ptr->store_rec;
2298e4b17023SJohn Marino 
2299e4b17023SJohn Marino 	  /* Skip the clobbers.  */
2300e4b17023SJohn Marino 	  while (!store_info->is_set)
2301e4b17023SJohn Marino 	    store_info = store_info->next;
2302e4b17023SJohn Marino 
2303e4b17023SJohn Marino 	  /* There are three cases here.  */
2304e4b17023SJohn Marino 	  if (store_info->group_id < 0)
2305e4b17023SJohn Marino 	    /* We have a cselib store followed by a read from a
2306e4b17023SJohn Marino 	       const base. */
2307e4b17023SJohn Marino 	    remove
2308e4b17023SJohn Marino 	      = canon_true_dependence (store_info->mem,
2309e4b17023SJohn Marino 				       GET_MODE (store_info->mem),
2310e4b17023SJohn Marino 				       store_info->mem_addr,
2311e4b17023SJohn Marino 				       mem, mem_addr);
2312e4b17023SJohn Marino 
2313e4b17023SJohn Marino 	  else if (group_id == store_info->group_id)
2314e4b17023SJohn Marino 	    {
2315e4b17023SJohn Marino 	      /* This is a block mode load.  We may get lucky and
2316e4b17023SJohn Marino 		 canon_true_dependence may save the day.  */
2317e4b17023SJohn Marino 	      if (width == -1)
2318e4b17023SJohn Marino 		remove
2319e4b17023SJohn Marino 		  = canon_true_dependence (store_info->mem,
2320e4b17023SJohn Marino 					   GET_MODE (store_info->mem),
2321e4b17023SJohn Marino 					   store_info->mem_addr,
2322e4b17023SJohn Marino 					   mem, mem_addr);
2323e4b17023SJohn Marino 
2324e4b17023SJohn Marino 	      /* If this read is just reading back something that we just
2325e4b17023SJohn Marino 		 stored, rewrite the read.  */
2326e4b17023SJohn Marino 	      else
2327e4b17023SJohn Marino 		{
2328e4b17023SJohn Marino 		  if (store_info->rhs
2329e4b17023SJohn Marino 		      && offset >= store_info->begin
2330e4b17023SJohn Marino 		      && offset + width <= store_info->end
2331e4b17023SJohn Marino 		      && all_positions_needed_p (store_info,
2332e4b17023SJohn Marino 						 offset - store_info->begin,
2333e4b17023SJohn Marino 						 width)
2334e4b17023SJohn Marino 		      && replace_read (store_info, i_ptr, read_info,
2335e4b17023SJohn Marino 				       insn_info, loc, bb_info->regs_live))
2336e4b17023SJohn Marino 		    return 0;
2337e4b17023SJohn Marino 
2338e4b17023SJohn Marino 		  /* The bases are the same, just see if the offsets
2339e4b17023SJohn Marino 		     overlap.  */
2340e4b17023SJohn Marino 		  if ((offset < store_info->end)
2341e4b17023SJohn Marino 		      && (offset + width > store_info->begin))
2342e4b17023SJohn Marino 		    remove = true;
2343e4b17023SJohn Marino 		}
2344e4b17023SJohn Marino 	    }
2345e4b17023SJohn Marino 
2346e4b17023SJohn Marino 	  /* else
2347e4b17023SJohn Marino 	     The else case that is missing here is that the
2348e4b17023SJohn Marino 	     bases are constant but different.  There is nothing
2349e4b17023SJohn Marino 	     to do here because there is no overlap.  */
2350e4b17023SJohn Marino 
2351e4b17023SJohn Marino 	  if (remove)
2352e4b17023SJohn Marino 	    {
2353e4b17023SJohn Marino 	      if (dump_file)
2354e4b17023SJohn Marino 		dump_insn_info ("removing from active", i_ptr);
2355e4b17023SJohn Marino 
2356e4b17023SJohn Marino 	      active_local_stores_len--;
2357e4b17023SJohn Marino 	      if (last)
2358e4b17023SJohn Marino 		last->next_local_store = i_ptr->next_local_store;
2359e4b17023SJohn Marino 	      else
2360e4b17023SJohn Marino 		active_local_stores = i_ptr->next_local_store;
2361e4b17023SJohn Marino 	    }
2362e4b17023SJohn Marino 	  else
2363e4b17023SJohn Marino 	    last = i_ptr;
2364e4b17023SJohn Marino 	  i_ptr = i_ptr->next_local_store;
2365e4b17023SJohn Marino 	}
2366e4b17023SJohn Marino     }
2367e4b17023SJohn Marino   else
2368e4b17023SJohn Marino     {
2369e4b17023SJohn Marino       insn_info_t i_ptr = active_local_stores;
2370e4b17023SJohn Marino       insn_info_t last = NULL;
2371e4b17023SJohn Marino       if (dump_file)
2372e4b17023SJohn Marino 	{
2373e4b17023SJohn Marino 	  fprintf (dump_file, " processing cselib load mem:");
2374e4b17023SJohn Marino 	  print_inline_rtx (dump_file, mem, 0);
2375e4b17023SJohn Marino 	  fprintf (dump_file, "\n");
2376e4b17023SJohn Marino 	}
2377e4b17023SJohn Marino 
2378e4b17023SJohn Marino       while (i_ptr)
2379e4b17023SJohn Marino 	{
2380e4b17023SJohn Marino 	  bool remove = false;
2381e4b17023SJohn Marino 	  store_info_t store_info = i_ptr->store_rec;
2382e4b17023SJohn Marino 
2383e4b17023SJohn Marino 	  if (dump_file)
2384e4b17023SJohn Marino 	    fprintf (dump_file, " processing cselib load against insn %d\n",
2385e4b17023SJohn Marino 		     INSN_UID (i_ptr->insn));
2386e4b17023SJohn Marino 
2387e4b17023SJohn Marino 	  /* Skip the clobbers.  */
2388e4b17023SJohn Marino 	  while (!store_info->is_set)
2389e4b17023SJohn Marino 	    store_info = store_info->next;
2390e4b17023SJohn Marino 
2391e4b17023SJohn Marino 	  /* If this read is just reading back something that we just
2392e4b17023SJohn Marino 	     stored, rewrite the read.  */
2393e4b17023SJohn Marino 	  if (store_info->rhs
2394e4b17023SJohn Marino 	      && store_info->group_id == -1
2395e4b17023SJohn Marino 	      && store_info->cse_base == base
2396e4b17023SJohn Marino 	      && width != -1
2397e4b17023SJohn Marino 	      && offset >= store_info->begin
2398e4b17023SJohn Marino 	      && offset + width <= store_info->end
2399e4b17023SJohn Marino 	      && all_positions_needed_p (store_info,
2400e4b17023SJohn Marino 					 offset - store_info->begin, width)
2401e4b17023SJohn Marino 	      && replace_read (store_info, i_ptr,  read_info, insn_info, loc,
2402e4b17023SJohn Marino 			       bb_info->regs_live))
2403e4b17023SJohn Marino 	    return 0;
2404e4b17023SJohn Marino 
2405e4b17023SJohn Marino 	  if (!store_info->alias_set)
2406e4b17023SJohn Marino 	    remove = canon_true_dependence (store_info->mem,
2407e4b17023SJohn Marino 					    GET_MODE (store_info->mem),
2408e4b17023SJohn Marino 					    store_info->mem_addr,
2409e4b17023SJohn Marino 					    mem, mem_addr);
2410e4b17023SJohn Marino 
2411e4b17023SJohn Marino 	  if (remove)
2412e4b17023SJohn Marino 	    {
2413e4b17023SJohn Marino 	      if (dump_file)
2414e4b17023SJohn Marino 		dump_insn_info ("removing from active", i_ptr);
2415e4b17023SJohn Marino 
2416e4b17023SJohn Marino 	      active_local_stores_len--;
2417e4b17023SJohn Marino 	      if (last)
2418e4b17023SJohn Marino 		last->next_local_store = i_ptr->next_local_store;
2419e4b17023SJohn Marino 	      else
2420e4b17023SJohn Marino 		active_local_stores = i_ptr->next_local_store;
2421e4b17023SJohn Marino 	    }
2422e4b17023SJohn Marino 	  else
2423e4b17023SJohn Marino 	    last = i_ptr;
2424e4b17023SJohn Marino 	  i_ptr = i_ptr->next_local_store;
2425e4b17023SJohn Marino 	}
2426e4b17023SJohn Marino     }
2427e4b17023SJohn Marino   return 0;
2428e4b17023SJohn Marino }
2429e4b17023SJohn Marino 
2430e4b17023SJohn Marino /* A for_each_rtx callback in which DATA points the INSN_INFO for
2431e4b17023SJohn Marino    as check_mem_read_rtx.  Nullify the pointer if i_m_r_m_r returns
2432e4b17023SJohn Marino    true for any part of *LOC.  */
2433e4b17023SJohn Marino 
2434e4b17023SJohn Marino static void
check_mem_read_use(rtx * loc,void * data)2435e4b17023SJohn Marino check_mem_read_use (rtx *loc, void *data)
2436e4b17023SJohn Marino {
2437e4b17023SJohn Marino   for_each_rtx (loc, check_mem_read_rtx, data);
2438e4b17023SJohn Marino }
2439e4b17023SJohn Marino 
2440e4b17023SJohn Marino 
2441e4b17023SJohn Marino /* Get arguments passed to CALL_INSN.  Return TRUE if successful.
2442e4b17023SJohn Marino    So far it only handles arguments passed in registers.  */
2443e4b17023SJohn Marino 
2444e4b17023SJohn Marino static bool
get_call_args(rtx call_insn,tree fn,rtx * args,int nargs)2445e4b17023SJohn Marino get_call_args (rtx call_insn, tree fn, rtx *args, int nargs)
2446e4b17023SJohn Marino {
2447e4b17023SJohn Marino   CUMULATIVE_ARGS args_so_far_v;
2448e4b17023SJohn Marino   cumulative_args_t args_so_far;
2449e4b17023SJohn Marino   tree arg;
2450e4b17023SJohn Marino   int idx;
2451e4b17023SJohn Marino 
2452e4b17023SJohn Marino   INIT_CUMULATIVE_ARGS (args_so_far_v, TREE_TYPE (fn), NULL_RTX, 0, 3);
2453e4b17023SJohn Marino   args_so_far = pack_cumulative_args (&args_so_far_v);
2454e4b17023SJohn Marino 
2455e4b17023SJohn Marino   arg = TYPE_ARG_TYPES (TREE_TYPE (fn));
2456e4b17023SJohn Marino   for (idx = 0;
2457e4b17023SJohn Marino        arg != void_list_node && idx < nargs;
2458e4b17023SJohn Marino        arg = TREE_CHAIN (arg), idx++)
2459e4b17023SJohn Marino     {
2460e4b17023SJohn Marino       enum machine_mode mode = TYPE_MODE (TREE_VALUE (arg));
2461e4b17023SJohn Marino       rtx reg, link, tmp;
2462e4b17023SJohn Marino       reg = targetm.calls.function_arg (args_so_far, mode, NULL_TREE, true);
2463e4b17023SJohn Marino       if (!reg || !REG_P (reg) || GET_MODE (reg) != mode
2464e4b17023SJohn Marino 	  || GET_MODE_CLASS (mode) != MODE_INT)
2465e4b17023SJohn Marino 	return false;
2466e4b17023SJohn Marino 
2467e4b17023SJohn Marino       for (link = CALL_INSN_FUNCTION_USAGE (call_insn);
2468e4b17023SJohn Marino 	   link;
2469e4b17023SJohn Marino 	   link = XEXP (link, 1))
2470e4b17023SJohn Marino 	if (GET_CODE (XEXP (link, 0)) == USE)
2471e4b17023SJohn Marino 	  {
2472e4b17023SJohn Marino 	    args[idx] = XEXP (XEXP (link, 0), 0);
2473e4b17023SJohn Marino 	    if (REG_P (args[idx])
2474e4b17023SJohn Marino 		&& REGNO (args[idx]) == REGNO (reg)
2475e4b17023SJohn Marino 		&& (GET_MODE (args[idx]) == mode
2476e4b17023SJohn Marino 		    || (GET_MODE_CLASS (GET_MODE (args[idx])) == MODE_INT
2477e4b17023SJohn Marino 			&& (GET_MODE_SIZE (GET_MODE (args[idx]))
2478e4b17023SJohn Marino 			    <= UNITS_PER_WORD)
2479e4b17023SJohn Marino 			&& (GET_MODE_SIZE (GET_MODE (args[idx]))
2480e4b17023SJohn Marino 			    > GET_MODE_SIZE (mode)))))
2481e4b17023SJohn Marino 	      break;
2482e4b17023SJohn Marino 	  }
2483e4b17023SJohn Marino       if (!link)
2484e4b17023SJohn Marino 	return false;
2485e4b17023SJohn Marino 
2486e4b17023SJohn Marino       tmp = cselib_expand_value_rtx (args[idx], scratch, 5);
2487e4b17023SJohn Marino       if (GET_MODE (args[idx]) != mode)
2488e4b17023SJohn Marino 	{
2489e4b17023SJohn Marino 	  if (!tmp || !CONST_INT_P (tmp))
2490e4b17023SJohn Marino 	    return false;
2491e4b17023SJohn Marino 	  tmp = gen_int_mode (INTVAL (tmp), mode);
2492e4b17023SJohn Marino 	}
2493e4b17023SJohn Marino       if (tmp)
2494e4b17023SJohn Marino 	args[idx] = tmp;
2495e4b17023SJohn Marino 
2496e4b17023SJohn Marino       targetm.calls.function_arg_advance (args_so_far, mode, NULL_TREE, true);
2497e4b17023SJohn Marino     }
2498e4b17023SJohn Marino   if (arg != void_list_node || idx != nargs)
2499e4b17023SJohn Marino     return false;
2500e4b17023SJohn Marino   return true;
2501e4b17023SJohn Marino }
2502e4b17023SJohn Marino 
2503e4b17023SJohn Marino /* Return a bitmap of the fixed registers contained in IN.  */
2504e4b17023SJohn Marino 
2505e4b17023SJohn Marino static bitmap
copy_fixed_regs(const_bitmap in)2506e4b17023SJohn Marino copy_fixed_regs (const_bitmap in)
2507e4b17023SJohn Marino {
2508e4b17023SJohn Marino   bitmap ret;
2509e4b17023SJohn Marino 
2510e4b17023SJohn Marino   ret = ALLOC_REG_SET (NULL);
2511e4b17023SJohn Marino   bitmap_and (ret, in, fixed_reg_set_regset);
2512e4b17023SJohn Marino   return ret;
2513e4b17023SJohn Marino }
2514e4b17023SJohn Marino 
2515e4b17023SJohn Marino /* Apply record_store to all candidate stores in INSN.  Mark INSN
2516e4b17023SJohn Marino    if some part of it is not a candidate store and assigns to a
2517e4b17023SJohn Marino    non-register target.  */
2518e4b17023SJohn Marino 
2519e4b17023SJohn Marino static void
scan_insn(bb_info_t bb_info,rtx insn)2520e4b17023SJohn Marino scan_insn (bb_info_t bb_info, rtx insn)
2521e4b17023SJohn Marino {
2522e4b17023SJohn Marino   rtx body;
2523e4b17023SJohn Marino   insn_info_t insn_info = (insn_info_t) pool_alloc (insn_info_pool);
2524e4b17023SJohn Marino   int mems_found = 0;
2525e4b17023SJohn Marino   memset (insn_info, 0, sizeof (struct insn_info));
2526e4b17023SJohn Marino 
2527e4b17023SJohn Marino   if (dump_file)
2528e4b17023SJohn Marino     fprintf (dump_file, "\n**scanning insn=%d\n",
2529e4b17023SJohn Marino 	     INSN_UID (insn));
2530e4b17023SJohn Marino 
2531e4b17023SJohn Marino   insn_info->prev_insn = bb_info->last_insn;
2532e4b17023SJohn Marino   insn_info->insn = insn;
2533e4b17023SJohn Marino   bb_info->last_insn = insn_info;
2534e4b17023SJohn Marino 
2535e4b17023SJohn Marino   if (DEBUG_INSN_P (insn))
2536e4b17023SJohn Marino     {
2537e4b17023SJohn Marino       insn_info->cannot_delete = true;
2538e4b17023SJohn Marino       return;
2539e4b17023SJohn Marino     }
2540e4b17023SJohn Marino 
2541e4b17023SJohn Marino   /* Cselib clears the table for this case, so we have to essentially
2542e4b17023SJohn Marino      do the same.  */
2543e4b17023SJohn Marino   if (NONJUMP_INSN_P (insn)
2544e4b17023SJohn Marino       && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
2545e4b17023SJohn Marino       && MEM_VOLATILE_P (PATTERN (insn)))
2546e4b17023SJohn Marino     {
2547e4b17023SJohn Marino       add_wild_read (bb_info);
2548e4b17023SJohn Marino       insn_info->cannot_delete = true;
2549e4b17023SJohn Marino       return;
2550e4b17023SJohn Marino     }
2551e4b17023SJohn Marino 
2552e4b17023SJohn Marino   /* Look at all of the uses in the insn.  */
2553e4b17023SJohn Marino   note_uses (&PATTERN (insn), check_mem_read_use, bb_info);
2554e4b17023SJohn Marino 
2555e4b17023SJohn Marino   if (CALL_P (insn))
2556e4b17023SJohn Marino     {
2557e4b17023SJohn Marino       bool const_call;
2558e4b17023SJohn Marino       tree memset_call = NULL_TREE;
2559e4b17023SJohn Marino 
2560e4b17023SJohn Marino       insn_info->cannot_delete = true;
2561e4b17023SJohn Marino 
2562e4b17023SJohn Marino       /* Const functions cannot do anything bad i.e. read memory,
2563e4b17023SJohn Marino 	 however, they can read their parameters which may have
2564e4b17023SJohn Marino 	 been pushed onto the stack.
2565e4b17023SJohn Marino 	 memset and bzero don't read memory either.  */
2566e4b17023SJohn Marino       const_call = RTL_CONST_CALL_P (insn);
2567e4b17023SJohn Marino       if (!const_call)
2568e4b17023SJohn Marino 	{
2569e4b17023SJohn Marino 	  rtx call = PATTERN (insn);
2570e4b17023SJohn Marino 	  if (GET_CODE (call) == PARALLEL)
2571e4b17023SJohn Marino 	    call = XVECEXP (call, 0, 0);
2572e4b17023SJohn Marino 	  if (GET_CODE (call) == SET)
2573e4b17023SJohn Marino 	    call = SET_SRC (call);
2574e4b17023SJohn Marino 	  if (GET_CODE (call) == CALL
2575e4b17023SJohn Marino 	      && MEM_P (XEXP (call, 0))
2576e4b17023SJohn Marino 	      && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
2577e4b17023SJohn Marino 	    {
2578e4b17023SJohn Marino 	      rtx symbol = XEXP (XEXP (call, 0), 0);
2579e4b17023SJohn Marino 	      if (SYMBOL_REF_DECL (symbol)
2580e4b17023SJohn Marino 		  && TREE_CODE (SYMBOL_REF_DECL (symbol)) == FUNCTION_DECL)
2581e4b17023SJohn Marino 		{
2582e4b17023SJohn Marino 		  if ((DECL_BUILT_IN_CLASS (SYMBOL_REF_DECL (symbol))
2583e4b17023SJohn Marino 		       == BUILT_IN_NORMAL
2584e4b17023SJohn Marino 		       && (DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol))
2585e4b17023SJohn Marino 			   == BUILT_IN_MEMSET))
2586e4b17023SJohn Marino 		      || SYMBOL_REF_DECL (symbol) == block_clear_fn)
2587e4b17023SJohn Marino 		    memset_call = SYMBOL_REF_DECL (symbol);
2588e4b17023SJohn Marino 		}
2589e4b17023SJohn Marino 	    }
2590e4b17023SJohn Marino 	}
2591e4b17023SJohn Marino       if (const_call || memset_call)
2592e4b17023SJohn Marino 	{
2593e4b17023SJohn Marino 	  insn_info_t i_ptr = active_local_stores;
2594e4b17023SJohn Marino 	  insn_info_t last = NULL;
2595e4b17023SJohn Marino 
2596e4b17023SJohn Marino 	  if (dump_file)
2597e4b17023SJohn Marino 	    fprintf (dump_file, "%s call %d\n",
2598e4b17023SJohn Marino 		     const_call ? "const" : "memset", INSN_UID (insn));
2599e4b17023SJohn Marino 
2600e4b17023SJohn Marino 	  /* See the head comment of the frame_read field.  */
2601e4b17023SJohn Marino 	  if (reload_completed)
2602e4b17023SJohn Marino 	    insn_info->frame_read = true;
2603e4b17023SJohn Marino 
2604e4b17023SJohn Marino 	  /* Loop over the active stores and remove those which are
2605e4b17023SJohn Marino 	     killed by the const function call.  */
2606e4b17023SJohn Marino 	  while (i_ptr)
2607e4b17023SJohn Marino 	    {
2608e4b17023SJohn Marino 	      bool remove_store = false;
2609e4b17023SJohn Marino 
2610e4b17023SJohn Marino 	      /* The stack pointer based stores are always killed.  */
2611e4b17023SJohn Marino 	      if (i_ptr->stack_pointer_based)
2612e4b17023SJohn Marino 	        remove_store = true;
2613e4b17023SJohn Marino 
2614e4b17023SJohn Marino 	      /* If the frame is read, the frame related stores are killed.  */
2615e4b17023SJohn Marino 	      else if (insn_info->frame_read)
2616e4b17023SJohn Marino 		{
2617e4b17023SJohn Marino 		  store_info_t store_info = i_ptr->store_rec;
2618e4b17023SJohn Marino 
2619e4b17023SJohn Marino 		  /* Skip the clobbers.  */
2620e4b17023SJohn Marino 		  while (!store_info->is_set)
2621e4b17023SJohn Marino 		    store_info = store_info->next;
2622e4b17023SJohn Marino 
2623e4b17023SJohn Marino 		  if (store_info->group_id >= 0
2624e4b17023SJohn Marino 		      && VEC_index (group_info_t, rtx_group_vec,
2625e4b17023SJohn Marino 				    store_info->group_id)->frame_related)
2626e4b17023SJohn Marino 		    remove_store = true;
2627e4b17023SJohn Marino 		}
2628e4b17023SJohn Marino 
2629e4b17023SJohn Marino 	      if (remove_store)
2630e4b17023SJohn Marino 		{
2631e4b17023SJohn Marino 		  if (dump_file)
2632e4b17023SJohn Marino 		    dump_insn_info ("removing from active", i_ptr);
2633e4b17023SJohn Marino 
2634e4b17023SJohn Marino 		  active_local_stores_len--;
2635e4b17023SJohn Marino 		  if (last)
2636e4b17023SJohn Marino 		    last->next_local_store = i_ptr->next_local_store;
2637e4b17023SJohn Marino 		  else
2638e4b17023SJohn Marino 		    active_local_stores = i_ptr->next_local_store;
2639e4b17023SJohn Marino 		}
2640e4b17023SJohn Marino 	      else
2641e4b17023SJohn Marino 		last = i_ptr;
2642e4b17023SJohn Marino 
2643e4b17023SJohn Marino 	      i_ptr = i_ptr->next_local_store;
2644e4b17023SJohn Marino 	    }
2645e4b17023SJohn Marino 
2646e4b17023SJohn Marino 	  if (memset_call)
2647e4b17023SJohn Marino 	    {
2648e4b17023SJohn Marino 	      rtx args[3];
2649e4b17023SJohn Marino 	      if (get_call_args (insn, memset_call, args, 3)
2650e4b17023SJohn Marino 		  && CONST_INT_P (args[1])
2651e4b17023SJohn Marino 		  && CONST_INT_P (args[2])
2652e4b17023SJohn Marino 		  && INTVAL (args[2]) > 0)
2653e4b17023SJohn Marino 		{
2654e4b17023SJohn Marino 		  rtx mem = gen_rtx_MEM (BLKmode, args[0]);
2655e4b17023SJohn Marino 		  set_mem_size (mem, INTVAL (args[2]));
2656e4b17023SJohn Marino 		  body = gen_rtx_SET (VOIDmode, mem, args[1]);
2657e4b17023SJohn Marino 		  mems_found += record_store (body, bb_info);
2658e4b17023SJohn Marino 		  if (dump_file)
2659e4b17023SJohn Marino 		    fprintf (dump_file, "handling memset as BLKmode store\n");
2660e4b17023SJohn Marino 		  if (mems_found == 1)
2661e4b17023SJohn Marino 		    {
2662e4b17023SJohn Marino 		      if (active_local_stores_len++
2663e4b17023SJohn Marino 			  >= PARAM_VALUE (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES))
2664e4b17023SJohn Marino 			{
2665e4b17023SJohn Marino 			  active_local_stores_len = 1;
2666e4b17023SJohn Marino 			  active_local_stores = NULL;
2667e4b17023SJohn Marino 			}
2668e4b17023SJohn Marino 		      insn_info->fixed_regs_live
2669e4b17023SJohn Marino 			= copy_fixed_regs (bb_info->regs_live);
2670e4b17023SJohn Marino 		      insn_info->next_local_store = active_local_stores;
2671e4b17023SJohn Marino 		      active_local_stores = insn_info;
2672e4b17023SJohn Marino 		    }
2673e4b17023SJohn Marino 		}
2674e4b17023SJohn Marino 	    }
2675e4b17023SJohn Marino 	}
2676e4b17023SJohn Marino 
2677e4b17023SJohn Marino       else
2678e4b17023SJohn Marino 	/* Every other call, including pure functions, may read any memory
2679e4b17023SJohn Marino            that is not relative to the frame.  */
2680e4b17023SJohn Marino         add_non_frame_wild_read (bb_info);
2681e4b17023SJohn Marino 
2682e4b17023SJohn Marino       return;
2683e4b17023SJohn Marino     }
2684e4b17023SJohn Marino 
2685e4b17023SJohn Marino   /* Assuming that there are sets in these insns, we cannot delete
2686e4b17023SJohn Marino      them.  */
2687e4b17023SJohn Marino   if ((GET_CODE (PATTERN (insn)) == CLOBBER)
2688e4b17023SJohn Marino       || volatile_refs_p (PATTERN (insn))
2689e4b17023SJohn Marino       || insn_could_throw_p (insn)
2690e4b17023SJohn Marino       || (RTX_FRAME_RELATED_P (insn))
2691e4b17023SJohn Marino       || find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX))
2692e4b17023SJohn Marino     insn_info->cannot_delete = true;
2693e4b17023SJohn Marino 
2694e4b17023SJohn Marino   body = PATTERN (insn);
2695e4b17023SJohn Marino   if (GET_CODE (body) == PARALLEL)
2696e4b17023SJohn Marino     {
2697e4b17023SJohn Marino       int i;
2698e4b17023SJohn Marino       for (i = 0; i < XVECLEN (body, 0); i++)
2699e4b17023SJohn Marino 	mems_found += record_store (XVECEXP (body, 0, i), bb_info);
2700e4b17023SJohn Marino     }
2701e4b17023SJohn Marino   else
2702e4b17023SJohn Marino     mems_found += record_store (body, bb_info);
2703e4b17023SJohn Marino 
2704e4b17023SJohn Marino   if (dump_file)
2705e4b17023SJohn Marino     fprintf (dump_file, "mems_found = %d, cannot_delete = %s\n",
2706e4b17023SJohn Marino 	     mems_found, insn_info->cannot_delete ? "true" : "false");
2707e4b17023SJohn Marino 
2708e4b17023SJohn Marino   /* If we found some sets of mems, add it into the active_local_stores so
2709e4b17023SJohn Marino      that it can be locally deleted if found dead or used for
2710e4b17023SJohn Marino      replace_read and redundant constant store elimination.  Otherwise mark
2711e4b17023SJohn Marino      it as cannot delete.  This simplifies the processing later.  */
2712e4b17023SJohn Marino   if (mems_found == 1)
2713e4b17023SJohn Marino     {
2714e4b17023SJohn Marino       if (active_local_stores_len++
2715e4b17023SJohn Marino 	  >= PARAM_VALUE (PARAM_MAX_DSE_ACTIVE_LOCAL_STORES))
2716e4b17023SJohn Marino 	{
2717e4b17023SJohn Marino 	  active_local_stores_len = 1;
2718e4b17023SJohn Marino 	  active_local_stores = NULL;
2719e4b17023SJohn Marino 	}
2720e4b17023SJohn Marino       insn_info->fixed_regs_live = copy_fixed_regs (bb_info->regs_live);
2721e4b17023SJohn Marino       insn_info->next_local_store = active_local_stores;
2722e4b17023SJohn Marino       active_local_stores = insn_info;
2723e4b17023SJohn Marino     }
2724e4b17023SJohn Marino   else
2725e4b17023SJohn Marino     insn_info->cannot_delete = true;
2726e4b17023SJohn Marino }
2727e4b17023SJohn Marino 
2728e4b17023SJohn Marino 
2729e4b17023SJohn Marino /* Remove BASE from the set of active_local_stores.  This is a
2730e4b17023SJohn Marino    callback from cselib that is used to get rid of the stores in
2731e4b17023SJohn Marino    active_local_stores.  */
2732e4b17023SJohn Marino 
2733e4b17023SJohn Marino static void
remove_useless_values(cselib_val * base)2734e4b17023SJohn Marino remove_useless_values (cselib_val *base)
2735e4b17023SJohn Marino {
2736e4b17023SJohn Marino   insn_info_t insn_info = active_local_stores;
2737e4b17023SJohn Marino   insn_info_t last = NULL;
2738e4b17023SJohn Marino 
2739e4b17023SJohn Marino   while (insn_info)
2740e4b17023SJohn Marino     {
2741e4b17023SJohn Marino       store_info_t store_info = insn_info->store_rec;
2742e4b17023SJohn Marino       bool del = false;
2743e4b17023SJohn Marino 
2744e4b17023SJohn Marino       /* If ANY of the store_infos match the cselib group that is
2745e4b17023SJohn Marino 	 being deleted, then the insn can not be deleted.  */
2746e4b17023SJohn Marino       while (store_info)
2747e4b17023SJohn Marino 	{
2748e4b17023SJohn Marino 	  if ((store_info->group_id == -1)
2749e4b17023SJohn Marino 	      && (store_info->cse_base == base))
2750e4b17023SJohn Marino 	    {
2751e4b17023SJohn Marino 	      del = true;
2752e4b17023SJohn Marino 	      break;
2753e4b17023SJohn Marino 	    }
2754e4b17023SJohn Marino 	  store_info = store_info->next;
2755e4b17023SJohn Marino 	}
2756e4b17023SJohn Marino 
2757e4b17023SJohn Marino       if (del)
2758e4b17023SJohn Marino 	{
2759e4b17023SJohn Marino 	  active_local_stores_len--;
2760e4b17023SJohn Marino 	  if (last)
2761e4b17023SJohn Marino 	    last->next_local_store = insn_info->next_local_store;
2762e4b17023SJohn Marino 	  else
2763e4b17023SJohn Marino 	    active_local_stores = insn_info->next_local_store;
2764e4b17023SJohn Marino 	  free_store_info (insn_info);
2765e4b17023SJohn Marino 	}
2766e4b17023SJohn Marino       else
2767e4b17023SJohn Marino 	last = insn_info;
2768e4b17023SJohn Marino 
2769e4b17023SJohn Marino       insn_info = insn_info->next_local_store;
2770e4b17023SJohn Marino     }
2771e4b17023SJohn Marino }
2772e4b17023SJohn Marino 
2773e4b17023SJohn Marino 
2774e4b17023SJohn Marino /* Do all of step 1.  */
2775e4b17023SJohn Marino 
2776e4b17023SJohn Marino static void
dse_step1(void)2777e4b17023SJohn Marino dse_step1 (void)
2778e4b17023SJohn Marino {
2779e4b17023SJohn Marino   basic_block bb;
2780e4b17023SJohn Marino   bitmap regs_live = BITMAP_ALLOC (NULL);
2781e4b17023SJohn Marino 
2782e4b17023SJohn Marino   cselib_init (0);
2783e4b17023SJohn Marino   all_blocks = BITMAP_ALLOC (NULL);
2784e4b17023SJohn Marino   bitmap_set_bit (all_blocks, ENTRY_BLOCK);
2785e4b17023SJohn Marino   bitmap_set_bit (all_blocks, EXIT_BLOCK);
2786e4b17023SJohn Marino 
2787e4b17023SJohn Marino   FOR_ALL_BB (bb)
2788e4b17023SJohn Marino     {
2789e4b17023SJohn Marino       insn_info_t ptr;
2790e4b17023SJohn Marino       bb_info_t bb_info = (bb_info_t) pool_alloc (bb_info_pool);
2791e4b17023SJohn Marino 
2792e4b17023SJohn Marino       memset (bb_info, 0, sizeof (struct bb_info));
2793e4b17023SJohn Marino       bitmap_set_bit (all_blocks, bb->index);
2794e4b17023SJohn Marino       bb_info->regs_live = regs_live;
2795e4b17023SJohn Marino 
2796e4b17023SJohn Marino       bitmap_copy (regs_live, DF_LR_IN (bb));
2797e4b17023SJohn Marino       df_simulate_initialize_forwards (bb, regs_live);
2798e4b17023SJohn Marino 
2799e4b17023SJohn Marino       bb_table[bb->index] = bb_info;
2800e4b17023SJohn Marino       cselib_discard_hook = remove_useless_values;
2801e4b17023SJohn Marino 
2802e4b17023SJohn Marino       if (bb->index >= NUM_FIXED_BLOCKS)
2803e4b17023SJohn Marino 	{
2804e4b17023SJohn Marino 	  rtx insn;
2805e4b17023SJohn Marino 
2806e4b17023SJohn Marino 	  cse_store_info_pool
2807e4b17023SJohn Marino 	    = create_alloc_pool ("cse_store_info_pool",
2808e4b17023SJohn Marino 				 sizeof (struct store_info), 100);
2809e4b17023SJohn Marino 	  active_local_stores = NULL;
2810e4b17023SJohn Marino 	  active_local_stores_len = 0;
2811e4b17023SJohn Marino 	  cselib_clear_table ();
2812e4b17023SJohn Marino 
2813e4b17023SJohn Marino 	  /* Scan the insns.  */
2814e4b17023SJohn Marino 	  FOR_BB_INSNS (bb, insn)
2815e4b17023SJohn Marino 	    {
2816e4b17023SJohn Marino 	      if (INSN_P (insn))
2817e4b17023SJohn Marino 		scan_insn (bb_info, insn);
2818e4b17023SJohn Marino 	      cselib_process_insn (insn);
2819e4b17023SJohn Marino 	      if (INSN_P (insn))
2820e4b17023SJohn Marino 		df_simulate_one_insn_forwards (bb, insn, regs_live);
2821e4b17023SJohn Marino 	    }
2822e4b17023SJohn Marino 
2823e4b17023SJohn Marino 	  /* This is something of a hack, because the global algorithm
2824e4b17023SJohn Marino 	     is supposed to take care of the case where stores go dead
2825e4b17023SJohn Marino 	     at the end of the function.  However, the global
2826e4b17023SJohn Marino 	     algorithm must take a more conservative view of block
2827e4b17023SJohn Marino 	     mode reads than the local alg does.  So to get the case
2828e4b17023SJohn Marino 	     where you have a store to the frame followed by a non
2829e4b17023SJohn Marino 	     overlapping block more read, we look at the active local
2830e4b17023SJohn Marino 	     stores at the end of the function and delete all of the
2831e4b17023SJohn Marino 	     frame and spill based ones.  */
2832e4b17023SJohn Marino 	  if (stores_off_frame_dead_at_return
2833e4b17023SJohn Marino 	      && (EDGE_COUNT (bb->succs) == 0
2834e4b17023SJohn Marino 		  || (single_succ_p (bb)
2835e4b17023SJohn Marino 		      && single_succ (bb) == EXIT_BLOCK_PTR
2836e4b17023SJohn Marino 		      && ! crtl->calls_eh_return)))
2837e4b17023SJohn Marino 	    {
2838e4b17023SJohn Marino 	      insn_info_t i_ptr = active_local_stores;
2839e4b17023SJohn Marino 	      while (i_ptr)
2840e4b17023SJohn Marino 		{
2841e4b17023SJohn Marino 		  store_info_t store_info = i_ptr->store_rec;
2842e4b17023SJohn Marino 
2843e4b17023SJohn Marino 		  /* Skip the clobbers.  */
2844e4b17023SJohn Marino 		  while (!store_info->is_set)
2845e4b17023SJohn Marino 		    store_info = store_info->next;
2846e4b17023SJohn Marino 		  if (store_info->alias_set && !i_ptr->cannot_delete)
2847e4b17023SJohn Marino 		    delete_dead_store_insn (i_ptr);
2848e4b17023SJohn Marino 		  else
2849e4b17023SJohn Marino 		    if (store_info->group_id >= 0)
2850e4b17023SJohn Marino 		      {
2851e4b17023SJohn Marino 			group_info_t group
2852e4b17023SJohn Marino 			  = VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
2853e4b17023SJohn Marino 			if (group->frame_related && !i_ptr->cannot_delete)
2854e4b17023SJohn Marino 			  delete_dead_store_insn (i_ptr);
2855e4b17023SJohn Marino 		      }
2856e4b17023SJohn Marino 
2857e4b17023SJohn Marino 		  i_ptr = i_ptr->next_local_store;
2858e4b17023SJohn Marino 		}
2859e4b17023SJohn Marino 	    }
2860e4b17023SJohn Marino 
2861e4b17023SJohn Marino 	  /* Get rid of the loads that were discovered in
2862e4b17023SJohn Marino 	     replace_read.  Cselib is finished with this block.  */
2863e4b17023SJohn Marino 	  while (deferred_change_list)
2864e4b17023SJohn Marino 	    {
2865e4b17023SJohn Marino 	      deferred_change_t next = deferred_change_list->next;
2866e4b17023SJohn Marino 
2867e4b17023SJohn Marino 	      /* There is no reason to validate this change.  That was
2868e4b17023SJohn Marino 		 done earlier.  */
2869e4b17023SJohn Marino 	      *deferred_change_list->loc = deferred_change_list->reg;
2870e4b17023SJohn Marino 	      pool_free (deferred_change_pool, deferred_change_list);
2871e4b17023SJohn Marino 	      deferred_change_list = next;
2872e4b17023SJohn Marino 	    }
2873e4b17023SJohn Marino 
2874e4b17023SJohn Marino 	  /* Get rid of all of the cselib based store_infos in this
2875e4b17023SJohn Marino 	     block and mark the containing insns as not being
2876e4b17023SJohn Marino 	     deletable.  */
2877e4b17023SJohn Marino 	  ptr = bb_info->last_insn;
2878e4b17023SJohn Marino 	  while (ptr)
2879e4b17023SJohn Marino 	    {
2880e4b17023SJohn Marino 	      if (ptr->contains_cselib_groups)
2881e4b17023SJohn Marino 		{
2882e4b17023SJohn Marino 		  store_info_t s_info = ptr->store_rec;
2883e4b17023SJohn Marino 		  while (s_info && !s_info->is_set)
2884e4b17023SJohn Marino 		    s_info = s_info->next;
2885e4b17023SJohn Marino 		  if (s_info
2886e4b17023SJohn Marino 		      && s_info->redundant_reason
2887e4b17023SJohn Marino 		      && s_info->redundant_reason->insn
2888e4b17023SJohn Marino 		      && !ptr->cannot_delete)
2889e4b17023SJohn Marino 		    {
2890e4b17023SJohn Marino 		      if (dump_file)
2891e4b17023SJohn Marino 			fprintf (dump_file, "Locally deleting insn %d "
2892e4b17023SJohn Marino 					    "because insn %d stores the "
2893e4b17023SJohn Marino 					    "same value and couldn't be "
2894e4b17023SJohn Marino 					    "eliminated\n",
2895e4b17023SJohn Marino 				 INSN_UID (ptr->insn),
2896e4b17023SJohn Marino 				 INSN_UID (s_info->redundant_reason->insn));
2897e4b17023SJohn Marino 		      delete_dead_store_insn (ptr);
2898e4b17023SJohn Marino 		    }
2899e4b17023SJohn Marino 		  if (s_info)
2900e4b17023SJohn Marino 		    s_info->redundant_reason = NULL;
2901e4b17023SJohn Marino 		  free_store_info (ptr);
2902e4b17023SJohn Marino 		}
2903e4b17023SJohn Marino 	      else
2904e4b17023SJohn Marino 		{
2905e4b17023SJohn Marino 		  store_info_t s_info;
2906e4b17023SJohn Marino 
2907e4b17023SJohn Marino 		  /* Free at least positions_needed bitmaps.  */
2908e4b17023SJohn Marino 		  for (s_info = ptr->store_rec; s_info; s_info = s_info->next)
2909e4b17023SJohn Marino 		    if (s_info->is_large)
2910e4b17023SJohn Marino 		      {
2911e4b17023SJohn Marino 			BITMAP_FREE (s_info->positions_needed.large.bmap);
2912e4b17023SJohn Marino 			s_info->is_large = false;
2913e4b17023SJohn Marino 		      }
2914e4b17023SJohn Marino 		}
2915e4b17023SJohn Marino 	      ptr = ptr->prev_insn;
2916e4b17023SJohn Marino 	    }
2917e4b17023SJohn Marino 
2918e4b17023SJohn Marino 	  free_alloc_pool (cse_store_info_pool);
2919e4b17023SJohn Marino 	}
2920e4b17023SJohn Marino       bb_info->regs_live = NULL;
2921e4b17023SJohn Marino     }
2922e4b17023SJohn Marino 
2923e4b17023SJohn Marino   BITMAP_FREE (regs_live);
2924e4b17023SJohn Marino   cselib_finish ();
2925e4b17023SJohn Marino   htab_empty (rtx_group_table);
2926e4b17023SJohn Marino }
2927e4b17023SJohn Marino 
2928e4b17023SJohn Marino 
2929e4b17023SJohn Marino /*----------------------------------------------------------------------------
2930e4b17023SJohn Marino    Second step.
2931e4b17023SJohn Marino 
2932e4b17023SJohn Marino    Assign each byte position in the stores that we are going to
2933e4b17023SJohn Marino    analyze globally to a position in the bitmaps.  Returns true if
2934e4b17023SJohn Marino    there are any bit positions assigned.
2935e4b17023SJohn Marino ----------------------------------------------------------------------------*/
2936e4b17023SJohn Marino 
2937e4b17023SJohn Marino static void
dse_step2_init(void)2938e4b17023SJohn Marino dse_step2_init (void)
2939e4b17023SJohn Marino {
2940e4b17023SJohn Marino   unsigned int i;
2941e4b17023SJohn Marino   group_info_t group;
2942e4b17023SJohn Marino 
2943e4b17023SJohn Marino   FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
2944e4b17023SJohn Marino     {
2945e4b17023SJohn Marino       /* For all non stack related bases, we only consider a store to
2946e4b17023SJohn Marino 	 be deletable if there are two or more stores for that
2947e4b17023SJohn Marino 	 position.  This is because it takes one store to make the
2948e4b17023SJohn Marino 	 other store redundant.  However, for the stores that are
2949e4b17023SJohn Marino 	 stack related, we consider them if there is only one store
2950e4b17023SJohn Marino 	 for the position.  We do this because the stack related
2951e4b17023SJohn Marino 	 stores can be deleted if their is no read between them and
2952e4b17023SJohn Marino 	 the end of the function.
2953e4b17023SJohn Marino 
2954e4b17023SJohn Marino 	 To make this work in the current framework, we take the stack
2955e4b17023SJohn Marino 	 related bases add all of the bits from store1 into store2.
2956e4b17023SJohn Marino 	 This has the effect of making the eligible even if there is
2957e4b17023SJohn Marino 	 only one store.   */
2958e4b17023SJohn Marino 
2959e4b17023SJohn Marino       if (stores_off_frame_dead_at_return && group->frame_related)
2960e4b17023SJohn Marino 	{
2961e4b17023SJohn Marino 	  bitmap_ior_into (group->store2_n, group->store1_n);
2962e4b17023SJohn Marino 	  bitmap_ior_into (group->store2_p, group->store1_p);
2963e4b17023SJohn Marino 	  if (dump_file)
2964e4b17023SJohn Marino 	    fprintf (dump_file, "group %d is frame related ", i);
2965e4b17023SJohn Marino 	}
2966e4b17023SJohn Marino 
2967e4b17023SJohn Marino       group->offset_map_size_n++;
2968e4b17023SJohn Marino       group->offset_map_n = XNEWVEC (int, group->offset_map_size_n);
2969e4b17023SJohn Marino       group->offset_map_size_p++;
2970e4b17023SJohn Marino       group->offset_map_p = XNEWVEC (int, group->offset_map_size_p);
2971e4b17023SJohn Marino       group->process_globally = false;
2972e4b17023SJohn Marino       if (dump_file)
2973e4b17023SJohn Marino 	{
2974e4b17023SJohn Marino 	  fprintf (dump_file, "group %d(%d+%d): ", i,
2975e4b17023SJohn Marino 		   (int)bitmap_count_bits (group->store2_n),
2976e4b17023SJohn Marino 		   (int)bitmap_count_bits (group->store2_p));
2977e4b17023SJohn Marino 	  bitmap_print (dump_file, group->store2_n, "n ", " ");
2978e4b17023SJohn Marino 	  bitmap_print (dump_file, group->store2_p, "p ", "\n");
2979e4b17023SJohn Marino 	}
2980e4b17023SJohn Marino     }
2981e4b17023SJohn Marino }
2982e4b17023SJohn Marino 
2983e4b17023SJohn Marino 
2984e4b17023SJohn Marino /* Init the offset tables for the normal case.  */
2985e4b17023SJohn Marino 
2986e4b17023SJohn Marino static bool
dse_step2_nospill(void)2987e4b17023SJohn Marino dse_step2_nospill (void)
2988e4b17023SJohn Marino {
2989e4b17023SJohn Marino   unsigned int i;
2990e4b17023SJohn Marino   group_info_t group;
2991e4b17023SJohn Marino   /* Position 0 is unused because 0 is used in the maps to mean
2992e4b17023SJohn Marino      unused.  */
2993e4b17023SJohn Marino   current_position = 1;
2994e4b17023SJohn Marino   FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
2995e4b17023SJohn Marino     {
2996e4b17023SJohn Marino       bitmap_iterator bi;
2997e4b17023SJohn Marino       unsigned int j;
2998e4b17023SJohn Marino 
2999e4b17023SJohn Marino       if (group == clear_alias_group)
3000e4b17023SJohn Marino 	continue;
3001e4b17023SJohn Marino 
3002e4b17023SJohn Marino       memset (group->offset_map_n, 0, sizeof(int) * group->offset_map_size_n);
3003e4b17023SJohn Marino       memset (group->offset_map_p, 0, sizeof(int) * group->offset_map_size_p);
3004e4b17023SJohn Marino       bitmap_clear (group->group_kill);
3005e4b17023SJohn Marino 
3006e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (group->store2_n, 0, j, bi)
3007e4b17023SJohn Marino 	{
3008e4b17023SJohn Marino 	  bitmap_set_bit (group->group_kill, current_position);
3009e4b17023SJohn Marino           if (bitmap_bit_p (group->escaped_n, j))
3010e4b17023SJohn Marino 	    bitmap_set_bit (kill_on_calls, current_position);
3011e4b17023SJohn Marino 	  group->offset_map_n[j] = current_position++;
3012e4b17023SJohn Marino 	  group->process_globally = true;
3013e4b17023SJohn Marino 	}
3014e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (group->store2_p, 0, j, bi)
3015e4b17023SJohn Marino 	{
3016e4b17023SJohn Marino 	  bitmap_set_bit (group->group_kill, current_position);
3017e4b17023SJohn Marino           if (bitmap_bit_p (group->escaped_p, j))
3018e4b17023SJohn Marino 	    bitmap_set_bit (kill_on_calls, current_position);
3019e4b17023SJohn Marino 	  group->offset_map_p[j] = current_position++;
3020e4b17023SJohn Marino 	  group->process_globally = true;
3021e4b17023SJohn Marino 	}
3022e4b17023SJohn Marino     }
3023e4b17023SJohn Marino   return current_position != 1;
3024e4b17023SJohn Marino }
3025e4b17023SJohn Marino 
3026e4b17023SJohn Marino 
3027e4b17023SJohn Marino /* Init the offset tables for the spill case.  */
3028e4b17023SJohn Marino 
3029e4b17023SJohn Marino static bool
dse_step2_spill(void)3030e4b17023SJohn Marino dse_step2_spill (void)
3031e4b17023SJohn Marino {
3032e4b17023SJohn Marino   unsigned int j;
3033e4b17023SJohn Marino   group_info_t group = clear_alias_group;
3034e4b17023SJohn Marino   bitmap_iterator bi;
3035e4b17023SJohn Marino 
3036e4b17023SJohn Marino   /* Position 0 is unused because 0 is used in the maps to mean
3037e4b17023SJohn Marino      unused.  */
3038e4b17023SJohn Marino   current_position = 1;
3039e4b17023SJohn Marino 
3040e4b17023SJohn Marino   if (dump_file)
3041e4b17023SJohn Marino     {
3042e4b17023SJohn Marino       bitmap_print (dump_file, clear_alias_sets,
3043e4b17023SJohn Marino 		    "clear alias sets              ", "\n");
3044e4b17023SJohn Marino       bitmap_print (dump_file, disqualified_clear_alias_sets,
3045e4b17023SJohn Marino 		    "disqualified clear alias sets ", "\n");
3046e4b17023SJohn Marino     }
3047e4b17023SJohn Marino 
3048e4b17023SJohn Marino   memset (group->offset_map_n, 0, sizeof(int) * group->offset_map_size_n);
3049e4b17023SJohn Marino   memset (group->offset_map_p, 0, sizeof(int) * group->offset_map_size_p);
3050e4b17023SJohn Marino   bitmap_clear (group->group_kill);
3051e4b17023SJohn Marino 
3052e4b17023SJohn Marino   /* Remove the disqualified positions from the store2_p set.  */
3053e4b17023SJohn Marino   bitmap_and_compl_into (group->store2_p, disqualified_clear_alias_sets);
3054e4b17023SJohn Marino 
3055e4b17023SJohn Marino   /* We do not need to process the store2_n set because
3056e4b17023SJohn Marino      alias_sets are always positive.  */
3057e4b17023SJohn Marino   EXECUTE_IF_SET_IN_BITMAP (group->store2_p, 0, j, bi)
3058e4b17023SJohn Marino     {
3059e4b17023SJohn Marino       bitmap_set_bit (group->group_kill, current_position);
3060e4b17023SJohn Marino       group->offset_map_p[j] = current_position++;
3061e4b17023SJohn Marino       group->process_globally = true;
3062e4b17023SJohn Marino     }
3063e4b17023SJohn Marino 
3064e4b17023SJohn Marino   return current_position != 1;
3065e4b17023SJohn Marino }
3066e4b17023SJohn Marino 
3067e4b17023SJohn Marino 
3068e4b17023SJohn Marino 
3069e4b17023SJohn Marino /*----------------------------------------------------------------------------
3070e4b17023SJohn Marino   Third step.
3071e4b17023SJohn Marino 
3072e4b17023SJohn Marino   Build the bit vectors for the transfer functions.
3073e4b17023SJohn Marino ----------------------------------------------------------------------------*/
3074e4b17023SJohn Marino 
3075e4b17023SJohn Marino 
3076e4b17023SJohn Marino /* Note that this is NOT a general purpose function.  Any mem that has
3077e4b17023SJohn Marino    an alias set registered here expected to be COMPLETELY unaliased:
3078e4b17023SJohn Marino    i.e it's addresses are not and need not be examined.
3079e4b17023SJohn Marino 
3080e4b17023SJohn Marino    It is known that all references to this address will have this
3081e4b17023SJohn Marino    alias set and there are NO other references to this address in the
3082e4b17023SJohn Marino    function.
3083e4b17023SJohn Marino 
3084e4b17023SJohn Marino    Currently the only place that is known to be clean enough to use
3085e4b17023SJohn Marino    this interface is the code that assigns the spill locations.
3086e4b17023SJohn Marino 
3087e4b17023SJohn Marino    All of the mems that have alias_sets registered are subjected to a
3088e4b17023SJohn Marino    very powerful form of dse where function calls, volatile reads and
3089e4b17023SJohn Marino    writes, and reads from random location are not taken into account.
3090e4b17023SJohn Marino 
3091e4b17023SJohn Marino    It is also assumed that these locations go dead when the function
3092e4b17023SJohn Marino    returns.  This assumption could be relaxed if there were found to
3093e4b17023SJohn Marino    be places that this assumption was not correct.
3094e4b17023SJohn Marino 
3095e4b17023SJohn Marino    The MODE is passed in and saved.  The mode of each load or store to
3096e4b17023SJohn Marino    a mem with ALIAS_SET is checked against MEM.  If the size of that
3097e4b17023SJohn Marino    load or store is different from MODE, processing is halted on this
3098e4b17023SJohn Marino    alias set.  For the vast majority of aliases sets, all of the loads
3099e4b17023SJohn Marino    and stores will use the same mode.  But vectors are treated
3100e4b17023SJohn Marino    differently: the alias set is established for the entire vector,
3101e4b17023SJohn Marino    but reload will insert loads and stores for individual elements and
3102e4b17023SJohn Marino    we do not necessarily have the information to track those separate
3103e4b17023SJohn Marino    elements.  So when we see a mode mismatch, we just bail.  */
3104e4b17023SJohn Marino 
3105e4b17023SJohn Marino 
3106e4b17023SJohn Marino void
dse_record_singleton_alias_set(alias_set_type alias_set,enum machine_mode mode)3107e4b17023SJohn Marino dse_record_singleton_alias_set (alias_set_type alias_set,
3108e4b17023SJohn Marino 				enum machine_mode mode)
3109e4b17023SJohn Marino {
3110e4b17023SJohn Marino   struct clear_alias_mode_holder tmp_holder;
3111e4b17023SJohn Marino   struct clear_alias_mode_holder *entry;
3112e4b17023SJohn Marino   void **slot;
3113e4b17023SJohn Marino 
3114e4b17023SJohn Marino   /* If we are not going to run dse, we need to return now or there
3115e4b17023SJohn Marino      will be problems with allocating the bitmaps.  */
3116e4b17023SJohn Marino   if ((!gate_dse()) || !alias_set)
3117e4b17023SJohn Marino     return;
3118e4b17023SJohn Marino 
3119e4b17023SJohn Marino   if (!clear_alias_sets)
3120e4b17023SJohn Marino     {
3121e4b17023SJohn Marino       clear_alias_sets = BITMAP_ALLOC (NULL);
3122e4b17023SJohn Marino       disqualified_clear_alias_sets = BITMAP_ALLOC (NULL);
3123e4b17023SJohn Marino       clear_alias_mode_table = htab_create (11, clear_alias_mode_hash,
3124e4b17023SJohn Marino 					    clear_alias_mode_eq, NULL);
3125e4b17023SJohn Marino       clear_alias_mode_pool = create_alloc_pool ("clear_alias_mode_pool",
3126e4b17023SJohn Marino 						 sizeof (struct clear_alias_mode_holder), 100);
3127e4b17023SJohn Marino     }
3128e4b17023SJohn Marino 
3129e4b17023SJohn Marino   bitmap_set_bit (clear_alias_sets, alias_set);
3130e4b17023SJohn Marino 
3131e4b17023SJohn Marino   tmp_holder.alias_set = alias_set;
3132e4b17023SJohn Marino 
3133e4b17023SJohn Marino   slot = htab_find_slot (clear_alias_mode_table, &tmp_holder, INSERT);
3134e4b17023SJohn Marino   gcc_assert (*slot == NULL);
3135e4b17023SJohn Marino 
3136e4b17023SJohn Marino   *slot = entry =
3137e4b17023SJohn Marino     (struct clear_alias_mode_holder *) pool_alloc (clear_alias_mode_pool);
3138e4b17023SJohn Marino   entry->alias_set = alias_set;
3139e4b17023SJohn Marino   entry->mode = mode;
3140e4b17023SJohn Marino }
3141e4b17023SJohn Marino 
3142e4b17023SJohn Marino 
3143e4b17023SJohn Marino /* Remove ALIAS_SET from the sets of stack slots being considered.  */
3144e4b17023SJohn Marino 
3145e4b17023SJohn Marino void
dse_invalidate_singleton_alias_set(alias_set_type alias_set)3146e4b17023SJohn Marino dse_invalidate_singleton_alias_set (alias_set_type alias_set)
3147e4b17023SJohn Marino {
3148e4b17023SJohn Marino   if ((!gate_dse()) || !alias_set)
3149e4b17023SJohn Marino     return;
3150e4b17023SJohn Marino 
3151e4b17023SJohn Marino   bitmap_clear_bit (clear_alias_sets, alias_set);
3152e4b17023SJohn Marino }
3153e4b17023SJohn Marino 
3154e4b17023SJohn Marino 
3155e4b17023SJohn Marino /* Look up the bitmap index for OFFSET in GROUP_INFO.  If it is not
3156e4b17023SJohn Marino    there, return 0.  */
3157e4b17023SJohn Marino 
3158e4b17023SJohn Marino static int
get_bitmap_index(group_info_t group_info,HOST_WIDE_INT offset)3159e4b17023SJohn Marino get_bitmap_index (group_info_t group_info, HOST_WIDE_INT offset)
3160e4b17023SJohn Marino {
3161e4b17023SJohn Marino   if (offset < 0)
3162e4b17023SJohn Marino     {
3163e4b17023SJohn Marino       HOST_WIDE_INT offset_p = -offset;
3164e4b17023SJohn Marino       if (offset_p >= group_info->offset_map_size_n)
3165e4b17023SJohn Marino 	return 0;
3166e4b17023SJohn Marino       return group_info->offset_map_n[offset_p];
3167e4b17023SJohn Marino     }
3168e4b17023SJohn Marino   else
3169e4b17023SJohn Marino     {
3170e4b17023SJohn Marino       if (offset >= group_info->offset_map_size_p)
3171e4b17023SJohn Marino 	return 0;
3172e4b17023SJohn Marino       return group_info->offset_map_p[offset];
3173e4b17023SJohn Marino     }
3174e4b17023SJohn Marino }
3175e4b17023SJohn Marino 
3176e4b17023SJohn Marino 
3177e4b17023SJohn Marino /* Process the STORE_INFOs into the bitmaps into GEN and KILL.  KILL
3178e4b17023SJohn Marino    may be NULL. */
3179e4b17023SJohn Marino 
3180e4b17023SJohn Marino static void
scan_stores_nospill(store_info_t store_info,bitmap gen,bitmap kill)3181e4b17023SJohn Marino scan_stores_nospill (store_info_t store_info, bitmap gen, bitmap kill)
3182e4b17023SJohn Marino {
3183e4b17023SJohn Marino   while (store_info)
3184e4b17023SJohn Marino     {
3185e4b17023SJohn Marino       HOST_WIDE_INT i;
3186e4b17023SJohn Marino       group_info_t group_info
3187e4b17023SJohn Marino 	= VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
3188e4b17023SJohn Marino       if (group_info->process_globally)
3189e4b17023SJohn Marino 	for (i = store_info->begin; i < store_info->end; i++)
3190e4b17023SJohn Marino 	  {
3191e4b17023SJohn Marino 	    int index = get_bitmap_index (group_info, i);
3192e4b17023SJohn Marino 	    if (index != 0)
3193e4b17023SJohn Marino 	      {
3194e4b17023SJohn Marino 		bitmap_set_bit (gen, index);
3195e4b17023SJohn Marino 		if (kill)
3196e4b17023SJohn Marino 		  bitmap_clear_bit (kill, index);
3197e4b17023SJohn Marino 	      }
3198e4b17023SJohn Marino 	  }
3199e4b17023SJohn Marino       store_info = store_info->next;
3200e4b17023SJohn Marino     }
3201e4b17023SJohn Marino }
3202e4b17023SJohn Marino 
3203e4b17023SJohn Marino 
3204e4b17023SJohn Marino /* Process the STORE_INFOs into the bitmaps into GEN and KILL.  KILL
3205e4b17023SJohn Marino    may be NULL. */
3206e4b17023SJohn Marino 
3207e4b17023SJohn Marino static void
scan_stores_spill(store_info_t store_info,bitmap gen,bitmap kill)3208e4b17023SJohn Marino scan_stores_spill (store_info_t store_info, bitmap gen, bitmap kill)
3209e4b17023SJohn Marino {
3210e4b17023SJohn Marino   while (store_info)
3211e4b17023SJohn Marino     {
3212e4b17023SJohn Marino       if (store_info->alias_set)
3213e4b17023SJohn Marino 	{
3214e4b17023SJohn Marino 	  int index = get_bitmap_index (clear_alias_group,
3215e4b17023SJohn Marino 					store_info->alias_set);
3216e4b17023SJohn Marino 	  if (index != 0)
3217e4b17023SJohn Marino 	    {
3218e4b17023SJohn Marino 	      bitmap_set_bit (gen, index);
3219e4b17023SJohn Marino 	      if (kill)
3220e4b17023SJohn Marino 		bitmap_clear_bit (kill, index);
3221e4b17023SJohn Marino 	    }
3222e4b17023SJohn Marino 	}
3223e4b17023SJohn Marino       store_info = store_info->next;
3224e4b17023SJohn Marino     }
3225e4b17023SJohn Marino }
3226e4b17023SJohn Marino 
3227e4b17023SJohn Marino 
3228e4b17023SJohn Marino /* Process the READ_INFOs into the bitmaps into GEN and KILL.  KILL
3229e4b17023SJohn Marino    may be NULL.  */
3230e4b17023SJohn Marino 
3231e4b17023SJohn Marino static void
scan_reads_nospill(insn_info_t insn_info,bitmap gen,bitmap kill)3232e4b17023SJohn Marino scan_reads_nospill (insn_info_t insn_info, bitmap gen, bitmap kill)
3233e4b17023SJohn Marino {
3234e4b17023SJohn Marino   read_info_t read_info = insn_info->read_rec;
3235e4b17023SJohn Marino   int i;
3236e4b17023SJohn Marino   group_info_t group;
3237e4b17023SJohn Marino 
3238e4b17023SJohn Marino   /* If this insn reads the frame, kill all the frame related stores.  */
3239e4b17023SJohn Marino   if (insn_info->frame_read)
3240e4b17023SJohn Marino     {
3241e4b17023SJohn Marino       FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
3242e4b17023SJohn Marino 	if (group->process_globally && group->frame_related)
3243e4b17023SJohn Marino 	  {
3244e4b17023SJohn Marino 	    if (kill)
3245e4b17023SJohn Marino 	      bitmap_ior_into (kill, group->group_kill);
3246e4b17023SJohn Marino 	    bitmap_and_compl_into (gen, group->group_kill);
3247e4b17023SJohn Marino 	  }
3248e4b17023SJohn Marino     }
3249e4b17023SJohn Marino   if (insn_info->non_frame_wild_read)
3250e4b17023SJohn Marino     {
3251e4b17023SJohn Marino       /* Kill all non-frame related stores.  Kill all stores of variables that
3252e4b17023SJohn Marino          escape.  */
3253e4b17023SJohn Marino       if (kill)
3254e4b17023SJohn Marino         bitmap_ior_into (kill, kill_on_calls);
3255e4b17023SJohn Marino       bitmap_and_compl_into (gen, kill_on_calls);
3256e4b17023SJohn Marino       FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
3257e4b17023SJohn Marino 	if (group->process_globally && !group->frame_related)
3258e4b17023SJohn Marino 	  {
3259e4b17023SJohn Marino 	    if (kill)
3260e4b17023SJohn Marino 	      bitmap_ior_into (kill, group->group_kill);
3261e4b17023SJohn Marino 	    bitmap_and_compl_into (gen, group->group_kill);
3262e4b17023SJohn Marino 	  }
3263e4b17023SJohn Marino     }
3264e4b17023SJohn Marino   while (read_info)
3265e4b17023SJohn Marino     {
3266e4b17023SJohn Marino       FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
3267e4b17023SJohn Marino 	{
3268e4b17023SJohn Marino 	  if (group->process_globally)
3269e4b17023SJohn Marino 	    {
3270e4b17023SJohn Marino 	      if (i == read_info->group_id)
3271e4b17023SJohn Marino 		{
3272e4b17023SJohn Marino 		  if (read_info->begin > read_info->end)
3273e4b17023SJohn Marino 		    {
3274e4b17023SJohn Marino 		      /* Begin > end for block mode reads.  */
3275e4b17023SJohn Marino 		      if (kill)
3276e4b17023SJohn Marino 			bitmap_ior_into (kill, group->group_kill);
3277e4b17023SJohn Marino 		      bitmap_and_compl_into (gen, group->group_kill);
3278e4b17023SJohn Marino 		    }
3279e4b17023SJohn Marino 		  else
3280e4b17023SJohn Marino 		    {
3281e4b17023SJohn Marino 		      /* The groups are the same, just process the
3282e4b17023SJohn Marino 			 offsets.  */
3283e4b17023SJohn Marino 		      HOST_WIDE_INT j;
3284e4b17023SJohn Marino 		      for (j = read_info->begin; j < read_info->end; j++)
3285e4b17023SJohn Marino 			{
3286e4b17023SJohn Marino 			  int index = get_bitmap_index (group, j);
3287e4b17023SJohn Marino 			  if (index != 0)
3288e4b17023SJohn Marino 			    {
3289e4b17023SJohn Marino 			      if (kill)
3290e4b17023SJohn Marino 				bitmap_set_bit (kill, index);
3291e4b17023SJohn Marino 			      bitmap_clear_bit (gen, index);
3292e4b17023SJohn Marino 			    }
3293e4b17023SJohn Marino 			}
3294e4b17023SJohn Marino 		    }
3295e4b17023SJohn Marino 		}
3296e4b17023SJohn Marino 	      else
3297e4b17023SJohn Marino 		{
3298e4b17023SJohn Marino 		  /* The groups are different, if the alias sets
3299e4b17023SJohn Marino 		     conflict, clear the entire group.  We only need
3300e4b17023SJohn Marino 		     to apply this test if the read_info is a cselib
3301e4b17023SJohn Marino 		     read.  Anything with a constant base cannot alias
3302e4b17023SJohn Marino 		     something else with a different constant
3303e4b17023SJohn Marino 		     base.  */
3304e4b17023SJohn Marino 		  if ((read_info->group_id < 0)
3305e4b17023SJohn Marino 		      && canon_true_dependence (group->base_mem,
3306e4b17023SJohn Marino 						GET_MODE (group->base_mem),
3307e4b17023SJohn Marino 						group->canon_base_addr,
3308e4b17023SJohn Marino 						read_info->mem, NULL_RTX))
3309e4b17023SJohn Marino 		    {
3310e4b17023SJohn Marino 		      if (kill)
3311e4b17023SJohn Marino 			bitmap_ior_into (kill, group->group_kill);
3312e4b17023SJohn Marino 		      bitmap_and_compl_into (gen, group->group_kill);
3313e4b17023SJohn Marino 		    }
3314e4b17023SJohn Marino 		}
3315e4b17023SJohn Marino 	    }
3316e4b17023SJohn Marino 	}
3317e4b17023SJohn Marino 
3318e4b17023SJohn Marino       read_info = read_info->next;
3319e4b17023SJohn Marino     }
3320e4b17023SJohn Marino }
3321e4b17023SJohn Marino 
3322e4b17023SJohn Marino /* Process the READ_INFOs into the bitmaps into GEN and KILL.  KILL
3323e4b17023SJohn Marino    may be NULL.  */
3324e4b17023SJohn Marino 
3325e4b17023SJohn Marino static void
scan_reads_spill(read_info_t read_info,bitmap gen,bitmap kill)3326e4b17023SJohn Marino scan_reads_spill (read_info_t read_info, bitmap gen, bitmap kill)
3327e4b17023SJohn Marino {
3328e4b17023SJohn Marino   while (read_info)
3329e4b17023SJohn Marino     {
3330e4b17023SJohn Marino       if (read_info->alias_set)
3331e4b17023SJohn Marino 	{
3332e4b17023SJohn Marino 	  int index = get_bitmap_index (clear_alias_group,
3333e4b17023SJohn Marino 					read_info->alias_set);
3334e4b17023SJohn Marino 	  if (index != 0)
3335e4b17023SJohn Marino 	    {
3336e4b17023SJohn Marino 	      if (kill)
3337e4b17023SJohn Marino 		bitmap_set_bit (kill, index);
3338e4b17023SJohn Marino 	      bitmap_clear_bit (gen, index);
3339e4b17023SJohn Marino 	    }
3340e4b17023SJohn Marino 	}
3341e4b17023SJohn Marino 
3342e4b17023SJohn Marino       read_info = read_info->next;
3343e4b17023SJohn Marino     }
3344e4b17023SJohn Marino }
3345e4b17023SJohn Marino 
3346e4b17023SJohn Marino 
3347e4b17023SJohn Marino /* Return the insn in BB_INFO before the first wild read or if there
3348e4b17023SJohn Marino    are no wild reads in the block, return the last insn.  */
3349e4b17023SJohn Marino 
3350e4b17023SJohn Marino static insn_info_t
find_insn_before_first_wild_read(bb_info_t bb_info)3351e4b17023SJohn Marino find_insn_before_first_wild_read (bb_info_t bb_info)
3352e4b17023SJohn Marino {
3353e4b17023SJohn Marino   insn_info_t insn_info = bb_info->last_insn;
3354e4b17023SJohn Marino   insn_info_t last_wild_read = NULL;
3355e4b17023SJohn Marino 
3356e4b17023SJohn Marino   while (insn_info)
3357e4b17023SJohn Marino     {
3358e4b17023SJohn Marino       if (insn_info->wild_read)
3359e4b17023SJohn Marino 	{
3360e4b17023SJohn Marino 	  last_wild_read = insn_info->prev_insn;
3361e4b17023SJohn Marino 	  /* Block starts with wild read.  */
3362e4b17023SJohn Marino 	  if (!last_wild_read)
3363e4b17023SJohn Marino 	    return NULL;
3364e4b17023SJohn Marino 	}
3365e4b17023SJohn Marino 
3366e4b17023SJohn Marino       insn_info = insn_info->prev_insn;
3367e4b17023SJohn Marino     }
3368e4b17023SJohn Marino 
3369e4b17023SJohn Marino   if (last_wild_read)
3370e4b17023SJohn Marino     return last_wild_read;
3371e4b17023SJohn Marino   else
3372e4b17023SJohn Marino     return bb_info->last_insn;
3373e4b17023SJohn Marino }
3374e4b17023SJohn Marino 
3375e4b17023SJohn Marino 
3376e4b17023SJohn Marino /* Scan the insns in BB_INFO starting at PTR and going to the top of
3377e4b17023SJohn Marino    the block in order to build the gen and kill sets for the block.
3378e4b17023SJohn Marino    We start at ptr which may be the last insn in the block or may be
3379e4b17023SJohn Marino    the first insn with a wild read.  In the latter case we are able to
3380e4b17023SJohn Marino    skip the rest of the block because it just does not matter:
3381e4b17023SJohn Marino    anything that happens is hidden by the wild read.  */
3382e4b17023SJohn Marino 
3383e4b17023SJohn Marino static void
dse_step3_scan(bool for_spills,basic_block bb)3384e4b17023SJohn Marino dse_step3_scan (bool for_spills, basic_block bb)
3385e4b17023SJohn Marino {
3386e4b17023SJohn Marino   bb_info_t bb_info = bb_table[bb->index];
3387e4b17023SJohn Marino   insn_info_t insn_info;
3388e4b17023SJohn Marino 
3389e4b17023SJohn Marino   if (for_spills)
3390e4b17023SJohn Marino     /* There are no wild reads in the spill case.  */
3391e4b17023SJohn Marino     insn_info = bb_info->last_insn;
3392e4b17023SJohn Marino   else
3393e4b17023SJohn Marino     insn_info = find_insn_before_first_wild_read (bb_info);
3394e4b17023SJohn Marino 
3395e4b17023SJohn Marino   /* In the spill case or in the no_spill case if there is no wild
3396e4b17023SJohn Marino      read in the block, we will need a kill set.  */
3397e4b17023SJohn Marino   if (insn_info == bb_info->last_insn)
3398e4b17023SJohn Marino     {
3399e4b17023SJohn Marino       if (bb_info->kill)
3400e4b17023SJohn Marino 	bitmap_clear (bb_info->kill);
3401e4b17023SJohn Marino       else
3402e4b17023SJohn Marino 	bb_info->kill = BITMAP_ALLOC (NULL);
3403e4b17023SJohn Marino     }
3404e4b17023SJohn Marino   else
3405e4b17023SJohn Marino     if (bb_info->kill)
3406e4b17023SJohn Marino       BITMAP_FREE (bb_info->kill);
3407e4b17023SJohn Marino 
3408e4b17023SJohn Marino   while (insn_info)
3409e4b17023SJohn Marino     {
3410e4b17023SJohn Marino       /* There may have been code deleted by the dce pass run before
3411e4b17023SJohn Marino 	 this phase.  */
3412e4b17023SJohn Marino       if (insn_info->insn && INSN_P (insn_info->insn))
3413e4b17023SJohn Marino 	{
3414e4b17023SJohn Marino 	  /* Process the read(s) last.  */
3415e4b17023SJohn Marino 	  if (for_spills)
3416e4b17023SJohn Marino 	    {
3417e4b17023SJohn Marino 	      scan_stores_spill (insn_info->store_rec, bb_info->gen, bb_info->kill);
3418e4b17023SJohn Marino 	      scan_reads_spill (insn_info->read_rec, bb_info->gen, bb_info->kill);
3419e4b17023SJohn Marino 	    }
3420e4b17023SJohn Marino 	  else
3421e4b17023SJohn Marino 	    {
3422e4b17023SJohn Marino 	      scan_stores_nospill (insn_info->store_rec, bb_info->gen, bb_info->kill);
3423e4b17023SJohn Marino 	      scan_reads_nospill (insn_info, bb_info->gen, bb_info->kill);
3424e4b17023SJohn Marino 	    }
3425e4b17023SJohn Marino 	}
3426e4b17023SJohn Marino 
3427e4b17023SJohn Marino       insn_info = insn_info->prev_insn;
3428e4b17023SJohn Marino     }
3429e4b17023SJohn Marino }
3430e4b17023SJohn Marino 
3431e4b17023SJohn Marino 
3432e4b17023SJohn Marino /* Set the gen set of the exit block, and also any block with no
3433e4b17023SJohn Marino    successors that does not have a wild read.  */
3434e4b17023SJohn Marino 
3435e4b17023SJohn Marino static void
dse_step3_exit_block_scan(bb_info_t bb_info)3436e4b17023SJohn Marino dse_step3_exit_block_scan (bb_info_t bb_info)
3437e4b17023SJohn Marino {
3438e4b17023SJohn Marino   /* The gen set is all 0's for the exit block except for the
3439e4b17023SJohn Marino      frame_pointer_group.  */
3440e4b17023SJohn Marino 
3441e4b17023SJohn Marino   if (stores_off_frame_dead_at_return)
3442e4b17023SJohn Marino     {
3443e4b17023SJohn Marino       unsigned int i;
3444e4b17023SJohn Marino       group_info_t group;
3445e4b17023SJohn Marino 
3446e4b17023SJohn Marino       FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
3447e4b17023SJohn Marino 	{
3448e4b17023SJohn Marino 	  if (group->process_globally && group->frame_related)
3449e4b17023SJohn Marino 	    bitmap_ior_into (bb_info->gen, group->group_kill);
3450e4b17023SJohn Marino 	}
3451e4b17023SJohn Marino     }
3452e4b17023SJohn Marino }
3453e4b17023SJohn Marino 
3454e4b17023SJohn Marino 
3455e4b17023SJohn Marino /* Find all of the blocks that are not backwards reachable from the
3456e4b17023SJohn Marino    exit block or any block with no successors (BB).  These are the
3457e4b17023SJohn Marino    infinite loops or infinite self loops.  These blocks will still
3458e4b17023SJohn Marino    have their bits set in UNREACHABLE_BLOCKS.  */
3459e4b17023SJohn Marino 
3460e4b17023SJohn Marino static void
mark_reachable_blocks(sbitmap unreachable_blocks,basic_block bb)3461e4b17023SJohn Marino mark_reachable_blocks (sbitmap unreachable_blocks, basic_block bb)
3462e4b17023SJohn Marino {
3463e4b17023SJohn Marino   edge e;
3464e4b17023SJohn Marino   edge_iterator ei;
3465e4b17023SJohn Marino 
3466e4b17023SJohn Marino   if (TEST_BIT (unreachable_blocks, bb->index))
3467e4b17023SJohn Marino     {
3468e4b17023SJohn Marino       RESET_BIT (unreachable_blocks, bb->index);
3469e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->preds)
3470e4b17023SJohn Marino 	{
3471e4b17023SJohn Marino 	  mark_reachable_blocks (unreachable_blocks, e->src);
3472e4b17023SJohn Marino 	}
3473e4b17023SJohn Marino     }
3474e4b17023SJohn Marino }
3475e4b17023SJohn Marino 
3476e4b17023SJohn Marino /* Build the transfer functions for the function.  */
3477e4b17023SJohn Marino 
3478e4b17023SJohn Marino static void
dse_step3(bool for_spills)3479e4b17023SJohn Marino dse_step3 (bool for_spills)
3480e4b17023SJohn Marino {
3481e4b17023SJohn Marino   basic_block bb;
3482e4b17023SJohn Marino   sbitmap unreachable_blocks = sbitmap_alloc (last_basic_block);
3483e4b17023SJohn Marino   sbitmap_iterator sbi;
3484e4b17023SJohn Marino   bitmap all_ones = NULL;
3485e4b17023SJohn Marino   unsigned int i;
3486e4b17023SJohn Marino 
3487e4b17023SJohn Marino   sbitmap_ones (unreachable_blocks);
3488e4b17023SJohn Marino 
3489e4b17023SJohn Marino   FOR_ALL_BB (bb)
3490e4b17023SJohn Marino     {
3491e4b17023SJohn Marino       bb_info_t bb_info = bb_table[bb->index];
3492e4b17023SJohn Marino       if (bb_info->gen)
3493e4b17023SJohn Marino 	bitmap_clear (bb_info->gen);
3494e4b17023SJohn Marino       else
3495e4b17023SJohn Marino 	bb_info->gen = BITMAP_ALLOC (NULL);
3496e4b17023SJohn Marino 
3497e4b17023SJohn Marino       if (bb->index == ENTRY_BLOCK)
3498e4b17023SJohn Marino 	;
3499e4b17023SJohn Marino       else if (bb->index == EXIT_BLOCK)
3500e4b17023SJohn Marino 	dse_step3_exit_block_scan (bb_info);
3501e4b17023SJohn Marino       else
3502e4b17023SJohn Marino 	dse_step3_scan (for_spills, bb);
3503e4b17023SJohn Marino       if (EDGE_COUNT (bb->succs) == 0)
3504e4b17023SJohn Marino 	mark_reachable_blocks (unreachable_blocks, bb);
3505e4b17023SJohn Marino 
3506e4b17023SJohn Marino       /* If this is the second time dataflow is run, delete the old
3507e4b17023SJohn Marino 	 sets.  */
3508e4b17023SJohn Marino       if (bb_info->in)
3509e4b17023SJohn Marino 	BITMAP_FREE (bb_info->in);
3510e4b17023SJohn Marino       if (bb_info->out)
3511e4b17023SJohn Marino 	BITMAP_FREE (bb_info->out);
3512e4b17023SJohn Marino     }
3513e4b17023SJohn Marino 
3514e4b17023SJohn Marino   /* For any block in an infinite loop, we must initialize the out set
3515e4b17023SJohn Marino      to all ones.  This could be expensive, but almost never occurs in
3516e4b17023SJohn Marino      practice. However, it is common in regression tests.  */
3517e4b17023SJohn Marino   EXECUTE_IF_SET_IN_SBITMAP (unreachable_blocks, 0, i, sbi)
3518e4b17023SJohn Marino     {
3519e4b17023SJohn Marino       if (bitmap_bit_p (all_blocks, i))
3520e4b17023SJohn Marino 	{
3521e4b17023SJohn Marino 	  bb_info_t bb_info = bb_table[i];
3522e4b17023SJohn Marino 	  if (!all_ones)
3523e4b17023SJohn Marino 	    {
3524e4b17023SJohn Marino 	      unsigned int j;
3525e4b17023SJohn Marino 	      group_info_t group;
3526e4b17023SJohn Marino 
3527e4b17023SJohn Marino 	      all_ones = BITMAP_ALLOC (NULL);
3528e4b17023SJohn Marino 	      FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, j, group)
3529e4b17023SJohn Marino 		bitmap_ior_into (all_ones, group->group_kill);
3530e4b17023SJohn Marino 	    }
3531e4b17023SJohn Marino 	  if (!bb_info->out)
3532e4b17023SJohn Marino 	    {
3533e4b17023SJohn Marino 	      bb_info->out = BITMAP_ALLOC (NULL);
3534e4b17023SJohn Marino 	      bitmap_copy (bb_info->out, all_ones);
3535e4b17023SJohn Marino 	    }
3536e4b17023SJohn Marino 	}
3537e4b17023SJohn Marino     }
3538e4b17023SJohn Marino 
3539e4b17023SJohn Marino   if (all_ones)
3540e4b17023SJohn Marino     BITMAP_FREE (all_ones);
3541e4b17023SJohn Marino   sbitmap_free (unreachable_blocks);
3542e4b17023SJohn Marino }
3543e4b17023SJohn Marino 
3544e4b17023SJohn Marino 
3545e4b17023SJohn Marino 
3546e4b17023SJohn Marino /*----------------------------------------------------------------------------
3547e4b17023SJohn Marino    Fourth step.
3548e4b17023SJohn Marino 
3549e4b17023SJohn Marino    Solve the bitvector equations.
3550e4b17023SJohn Marino ----------------------------------------------------------------------------*/
3551e4b17023SJohn Marino 
3552e4b17023SJohn Marino 
3553e4b17023SJohn Marino /* Confluence function for blocks with no successors.  Create an out
3554e4b17023SJohn Marino    set from the gen set of the exit block.  This block logically has
3555e4b17023SJohn Marino    the exit block as a successor.  */
3556e4b17023SJohn Marino 
3557e4b17023SJohn Marino 
3558e4b17023SJohn Marino 
3559e4b17023SJohn Marino static void
dse_confluence_0(basic_block bb)3560e4b17023SJohn Marino dse_confluence_0 (basic_block bb)
3561e4b17023SJohn Marino {
3562e4b17023SJohn Marino   bb_info_t bb_info = bb_table[bb->index];
3563e4b17023SJohn Marino 
3564e4b17023SJohn Marino   if (bb->index == EXIT_BLOCK)
3565e4b17023SJohn Marino     return;
3566e4b17023SJohn Marino 
3567e4b17023SJohn Marino   if (!bb_info->out)
3568e4b17023SJohn Marino     {
3569e4b17023SJohn Marino       bb_info->out = BITMAP_ALLOC (NULL);
3570e4b17023SJohn Marino       bitmap_copy (bb_info->out, bb_table[EXIT_BLOCK]->gen);
3571e4b17023SJohn Marino     }
3572e4b17023SJohn Marino }
3573e4b17023SJohn Marino 
3574e4b17023SJohn Marino /* Propagate the information from the in set of the dest of E to the
3575e4b17023SJohn Marino    out set of the src of E.  If the various in or out sets are not
3576e4b17023SJohn Marino    there, that means they are all ones.  */
3577e4b17023SJohn Marino 
3578e4b17023SJohn Marino static bool
dse_confluence_n(edge e)3579e4b17023SJohn Marino dse_confluence_n (edge e)
3580e4b17023SJohn Marino {
3581e4b17023SJohn Marino   bb_info_t src_info = bb_table[e->src->index];
3582e4b17023SJohn Marino   bb_info_t dest_info = bb_table[e->dest->index];
3583e4b17023SJohn Marino 
3584e4b17023SJohn Marino   if (dest_info->in)
3585e4b17023SJohn Marino     {
3586e4b17023SJohn Marino       if (src_info->out)
3587e4b17023SJohn Marino 	bitmap_and_into (src_info->out, dest_info->in);
3588e4b17023SJohn Marino       else
3589e4b17023SJohn Marino 	{
3590e4b17023SJohn Marino 	  src_info->out = BITMAP_ALLOC (NULL);
3591e4b17023SJohn Marino 	  bitmap_copy (src_info->out, dest_info->in);
3592e4b17023SJohn Marino 	}
3593e4b17023SJohn Marino     }
3594e4b17023SJohn Marino   return true;
3595e4b17023SJohn Marino }
3596e4b17023SJohn Marino 
3597e4b17023SJohn Marino 
3598e4b17023SJohn Marino /* Propagate the info from the out to the in set of BB_INDEX's basic
3599e4b17023SJohn Marino    block.  There are three cases:
3600e4b17023SJohn Marino 
3601e4b17023SJohn Marino    1) The block has no kill set.  In this case the kill set is all
3602e4b17023SJohn Marino    ones.  It does not matter what the out set of the block is, none of
3603e4b17023SJohn Marino    the info can reach the top.  The only thing that reaches the top is
3604e4b17023SJohn Marino    the gen set and we just copy the set.
3605e4b17023SJohn Marino 
3606e4b17023SJohn Marino    2) There is a kill set but no out set and bb has successors.  In
3607e4b17023SJohn Marino    this case we just return. Eventually an out set will be created and
3608e4b17023SJohn Marino    it is better to wait than to create a set of ones.
3609e4b17023SJohn Marino 
3610e4b17023SJohn Marino    3) There is both a kill and out set.  We apply the obvious transfer
3611e4b17023SJohn Marino    function.
3612e4b17023SJohn Marino */
3613e4b17023SJohn Marino 
3614e4b17023SJohn Marino static bool
dse_transfer_function(int bb_index)3615e4b17023SJohn Marino dse_transfer_function (int bb_index)
3616e4b17023SJohn Marino {
3617e4b17023SJohn Marino   bb_info_t bb_info = bb_table[bb_index];
3618e4b17023SJohn Marino 
3619e4b17023SJohn Marino   if (bb_info->kill)
3620e4b17023SJohn Marino     {
3621e4b17023SJohn Marino       if (bb_info->out)
3622e4b17023SJohn Marino 	{
3623e4b17023SJohn Marino 	  /* Case 3 above.  */
3624e4b17023SJohn Marino 	  if (bb_info->in)
3625e4b17023SJohn Marino 	    return bitmap_ior_and_compl (bb_info->in, bb_info->gen,
3626e4b17023SJohn Marino 					 bb_info->out, bb_info->kill);
3627e4b17023SJohn Marino 	  else
3628e4b17023SJohn Marino 	    {
3629e4b17023SJohn Marino 	      bb_info->in = BITMAP_ALLOC (NULL);
3630e4b17023SJohn Marino 	      bitmap_ior_and_compl (bb_info->in, bb_info->gen,
3631e4b17023SJohn Marino 				    bb_info->out, bb_info->kill);
3632e4b17023SJohn Marino 	      return true;
3633e4b17023SJohn Marino 	    }
3634e4b17023SJohn Marino 	}
3635e4b17023SJohn Marino       else
3636e4b17023SJohn Marino 	/* Case 2 above.  */
3637e4b17023SJohn Marino 	return false;
3638e4b17023SJohn Marino     }
3639e4b17023SJohn Marino   else
3640e4b17023SJohn Marino     {
3641e4b17023SJohn Marino       /* Case 1 above.  If there is already an in set, nothing
3642e4b17023SJohn Marino 	 happens.  */
3643e4b17023SJohn Marino       if (bb_info->in)
3644e4b17023SJohn Marino 	return false;
3645e4b17023SJohn Marino       else
3646e4b17023SJohn Marino 	{
3647e4b17023SJohn Marino 	  bb_info->in = BITMAP_ALLOC (NULL);
3648e4b17023SJohn Marino 	  bitmap_copy (bb_info->in, bb_info->gen);
3649e4b17023SJohn Marino 	  return true;
3650e4b17023SJohn Marino 	}
3651e4b17023SJohn Marino     }
3652e4b17023SJohn Marino }
3653e4b17023SJohn Marino 
3654e4b17023SJohn Marino /* Solve the dataflow equations.  */
3655e4b17023SJohn Marino 
3656e4b17023SJohn Marino static void
dse_step4(void)3657e4b17023SJohn Marino dse_step4 (void)
3658e4b17023SJohn Marino {
3659e4b17023SJohn Marino   df_simple_dataflow (DF_BACKWARD, NULL, dse_confluence_0,
3660e4b17023SJohn Marino 		      dse_confluence_n, dse_transfer_function,
3661e4b17023SJohn Marino 	   	      all_blocks, df_get_postorder (DF_BACKWARD),
3662e4b17023SJohn Marino 		      df_get_n_blocks (DF_BACKWARD));
3663e4b17023SJohn Marino   if (dump_file)
3664e4b17023SJohn Marino     {
3665e4b17023SJohn Marino       basic_block bb;
3666e4b17023SJohn Marino 
3667e4b17023SJohn Marino       fprintf (dump_file, "\n\n*** Global dataflow info after analysis.\n");
3668e4b17023SJohn Marino       FOR_ALL_BB (bb)
3669e4b17023SJohn Marino 	{
3670e4b17023SJohn Marino 	  bb_info_t bb_info = bb_table[bb->index];
3671e4b17023SJohn Marino 
3672e4b17023SJohn Marino 	  df_print_bb_index (bb, dump_file);
3673e4b17023SJohn Marino 	  if (bb_info->in)
3674e4b17023SJohn Marino 	    bitmap_print (dump_file, bb_info->in, "  in:   ", "\n");
3675e4b17023SJohn Marino 	  else
3676e4b17023SJohn Marino 	    fprintf (dump_file, "  in:   *MISSING*\n");
3677e4b17023SJohn Marino 	  if (bb_info->gen)
3678e4b17023SJohn Marino 	    bitmap_print (dump_file, bb_info->gen, "  gen:  ", "\n");
3679e4b17023SJohn Marino 	  else
3680e4b17023SJohn Marino 	    fprintf (dump_file, "  gen:  *MISSING*\n");
3681e4b17023SJohn Marino 	  if (bb_info->kill)
3682e4b17023SJohn Marino 	    bitmap_print (dump_file, bb_info->kill, "  kill: ", "\n");
3683e4b17023SJohn Marino 	  else
3684e4b17023SJohn Marino 	    fprintf (dump_file, "  kill: *MISSING*\n");
3685e4b17023SJohn Marino 	  if (bb_info->out)
3686e4b17023SJohn Marino 	    bitmap_print (dump_file, bb_info->out, "  out:  ", "\n");
3687e4b17023SJohn Marino 	  else
3688e4b17023SJohn Marino 	    fprintf (dump_file, "  out:  *MISSING*\n\n");
3689e4b17023SJohn Marino 	}
3690e4b17023SJohn Marino     }
3691e4b17023SJohn Marino }
3692e4b17023SJohn Marino 
3693e4b17023SJohn Marino 
3694e4b17023SJohn Marino 
3695e4b17023SJohn Marino /*----------------------------------------------------------------------------
3696e4b17023SJohn Marino    Fifth step.
3697e4b17023SJohn Marino 
3698e4b17023SJohn Marino    Delete the stores that can only be deleted using the global information.
3699e4b17023SJohn Marino ----------------------------------------------------------------------------*/
3700e4b17023SJohn Marino 
3701e4b17023SJohn Marino 
3702e4b17023SJohn Marino static void
dse_step5_nospill(void)3703e4b17023SJohn Marino dse_step5_nospill (void)
3704e4b17023SJohn Marino {
3705e4b17023SJohn Marino   basic_block bb;
3706e4b17023SJohn Marino   FOR_EACH_BB (bb)
3707e4b17023SJohn Marino     {
3708e4b17023SJohn Marino       bb_info_t bb_info = bb_table[bb->index];
3709e4b17023SJohn Marino       insn_info_t insn_info = bb_info->last_insn;
3710e4b17023SJohn Marino       bitmap v = bb_info->out;
3711e4b17023SJohn Marino 
3712e4b17023SJohn Marino       while (insn_info)
3713e4b17023SJohn Marino 	{
3714e4b17023SJohn Marino 	  bool deleted = false;
3715e4b17023SJohn Marino 	  if (dump_file && insn_info->insn)
3716e4b17023SJohn Marino 	    {
3717e4b17023SJohn Marino 	      fprintf (dump_file, "starting to process insn %d\n",
3718e4b17023SJohn Marino 		       INSN_UID (insn_info->insn));
3719e4b17023SJohn Marino 	      bitmap_print (dump_file, v, "  v:  ", "\n");
3720e4b17023SJohn Marino 	    }
3721e4b17023SJohn Marino 
3722e4b17023SJohn Marino 	  /* There may have been code deleted by the dce pass run before
3723e4b17023SJohn Marino 	     this phase.  */
3724e4b17023SJohn Marino 	  if (insn_info->insn
3725e4b17023SJohn Marino 	      && INSN_P (insn_info->insn)
3726e4b17023SJohn Marino 	      && (!insn_info->cannot_delete)
3727e4b17023SJohn Marino 	      && (!bitmap_empty_p (v)))
3728e4b17023SJohn Marino 	    {
3729e4b17023SJohn Marino 	      store_info_t store_info = insn_info->store_rec;
3730e4b17023SJohn Marino 
3731e4b17023SJohn Marino 	      /* Try to delete the current insn.  */
3732e4b17023SJohn Marino 	      deleted = true;
3733e4b17023SJohn Marino 
3734e4b17023SJohn Marino 	      /* Skip the clobbers.  */
3735e4b17023SJohn Marino 	      while (!store_info->is_set)
3736e4b17023SJohn Marino 		store_info = store_info->next;
3737e4b17023SJohn Marino 
3738e4b17023SJohn Marino 	      if (store_info->alias_set)
3739e4b17023SJohn Marino 		deleted = false;
3740e4b17023SJohn Marino 	      else
3741e4b17023SJohn Marino 		{
3742e4b17023SJohn Marino 		  HOST_WIDE_INT i;
3743e4b17023SJohn Marino 		  group_info_t group_info
3744e4b17023SJohn Marino 		    = VEC_index (group_info_t, rtx_group_vec, store_info->group_id);
3745e4b17023SJohn Marino 
3746e4b17023SJohn Marino 		  for (i = store_info->begin; i < store_info->end; i++)
3747e4b17023SJohn Marino 		    {
3748e4b17023SJohn Marino 		      int index = get_bitmap_index (group_info, i);
3749e4b17023SJohn Marino 
3750e4b17023SJohn Marino 		      if (dump_file)
3751e4b17023SJohn Marino 			fprintf (dump_file, "i = %d, index = %d\n", (int)i, index);
3752e4b17023SJohn Marino 		      if (index == 0 || !bitmap_bit_p (v, index))
3753e4b17023SJohn Marino 			{
3754e4b17023SJohn Marino 			  if (dump_file)
3755e4b17023SJohn Marino 			    fprintf (dump_file, "failing at i = %d\n", (int)i);
3756e4b17023SJohn Marino 			  deleted = false;
3757e4b17023SJohn Marino 			  break;
3758e4b17023SJohn Marino 			}
3759e4b17023SJohn Marino 		    }
3760e4b17023SJohn Marino 		}
3761e4b17023SJohn Marino 	      if (deleted)
3762e4b17023SJohn Marino 		{
3763e4b17023SJohn Marino 		  if (dbg_cnt (dse)
3764e4b17023SJohn Marino 		      && check_for_inc_dec_1 (insn_info))
3765e4b17023SJohn Marino 		    {
3766e4b17023SJohn Marino 		      delete_insn (insn_info->insn);
3767e4b17023SJohn Marino 		      insn_info->insn = NULL;
3768e4b17023SJohn Marino 		      globally_deleted++;
3769e4b17023SJohn Marino 		    }
3770e4b17023SJohn Marino 		}
3771e4b17023SJohn Marino 	    }
3772e4b17023SJohn Marino 	  /* We do want to process the local info if the insn was
3773e4b17023SJohn Marino 	     deleted.  For instance, if the insn did a wild read, we
3774e4b17023SJohn Marino 	     no longer need to trash the info.  */
3775e4b17023SJohn Marino 	  if (insn_info->insn
3776e4b17023SJohn Marino 	      && INSN_P (insn_info->insn)
3777e4b17023SJohn Marino 	      && (!deleted))
3778e4b17023SJohn Marino 	    {
3779e4b17023SJohn Marino 	      scan_stores_nospill (insn_info->store_rec, v, NULL);
3780e4b17023SJohn Marino 	      if (insn_info->wild_read)
3781e4b17023SJohn Marino 		{
3782e4b17023SJohn Marino 		  if (dump_file)
3783e4b17023SJohn Marino 		    fprintf (dump_file, "wild read\n");
3784e4b17023SJohn Marino 		  bitmap_clear (v);
3785e4b17023SJohn Marino 		}
3786e4b17023SJohn Marino 	      else if (insn_info->read_rec
3787e4b17023SJohn Marino                        || insn_info->non_frame_wild_read)
3788e4b17023SJohn Marino 		{
3789e4b17023SJohn Marino 		  if (dump_file && !insn_info->non_frame_wild_read)
3790e4b17023SJohn Marino 		    fprintf (dump_file, "regular read\n");
3791e4b17023SJohn Marino                   else if (dump_file)
3792e4b17023SJohn Marino 		    fprintf (dump_file, "non-frame wild read\n");
3793e4b17023SJohn Marino 		  scan_reads_nospill (insn_info, v, NULL);
3794e4b17023SJohn Marino 		}
3795e4b17023SJohn Marino 	    }
3796e4b17023SJohn Marino 
3797e4b17023SJohn Marino 	  insn_info = insn_info->prev_insn;
3798e4b17023SJohn Marino 	}
3799e4b17023SJohn Marino     }
3800e4b17023SJohn Marino }
3801e4b17023SJohn Marino 
3802e4b17023SJohn Marino 
3803e4b17023SJohn Marino static void
dse_step5_spill(void)3804e4b17023SJohn Marino dse_step5_spill (void)
3805e4b17023SJohn Marino {
3806e4b17023SJohn Marino   basic_block bb;
3807e4b17023SJohn Marino   FOR_EACH_BB (bb)
3808e4b17023SJohn Marino     {
3809e4b17023SJohn Marino       bb_info_t bb_info = bb_table[bb->index];
3810e4b17023SJohn Marino       insn_info_t insn_info = bb_info->last_insn;
3811e4b17023SJohn Marino       bitmap v = bb_info->out;
3812e4b17023SJohn Marino 
3813e4b17023SJohn Marino       while (insn_info)
3814e4b17023SJohn Marino 	{
3815e4b17023SJohn Marino 	  bool deleted = false;
3816e4b17023SJohn Marino 	  /* There may have been code deleted by the dce pass run before
3817e4b17023SJohn Marino 	     this phase.  */
3818e4b17023SJohn Marino 	  if (insn_info->insn
3819e4b17023SJohn Marino 	      && INSN_P (insn_info->insn)
3820e4b17023SJohn Marino 	      && (!insn_info->cannot_delete)
3821e4b17023SJohn Marino 	      && (!bitmap_empty_p (v)))
3822e4b17023SJohn Marino 	    {
3823e4b17023SJohn Marino 	      /* Try to delete the current insn.  */
3824e4b17023SJohn Marino 	      store_info_t store_info = insn_info->store_rec;
3825e4b17023SJohn Marino 	      deleted = true;
3826e4b17023SJohn Marino 
3827e4b17023SJohn Marino 	      while (store_info)
3828e4b17023SJohn Marino 		{
3829e4b17023SJohn Marino 		  if (store_info->alias_set)
3830e4b17023SJohn Marino 		    {
3831e4b17023SJohn Marino 		      int index = get_bitmap_index (clear_alias_group,
3832e4b17023SJohn Marino 						    store_info->alias_set);
3833e4b17023SJohn Marino 		      if (index == 0 || !bitmap_bit_p (v, index))
3834e4b17023SJohn Marino 			{
3835e4b17023SJohn Marino 			  deleted = false;
3836e4b17023SJohn Marino 			  break;
3837e4b17023SJohn Marino 			}
3838e4b17023SJohn Marino 		    }
3839e4b17023SJohn Marino 		  else
3840e4b17023SJohn Marino 		    deleted = false;
3841e4b17023SJohn Marino 		  store_info = store_info->next;
3842e4b17023SJohn Marino 		}
3843e4b17023SJohn Marino 	      if (deleted && dbg_cnt (dse)
3844e4b17023SJohn Marino 		  && check_for_inc_dec_1 (insn_info))
3845e4b17023SJohn Marino 		{
3846e4b17023SJohn Marino 		  if (dump_file)
3847e4b17023SJohn Marino 		    fprintf (dump_file, "Spill deleting insn %d\n",
3848e4b17023SJohn Marino 			     INSN_UID (insn_info->insn));
3849e4b17023SJohn Marino 		  delete_insn (insn_info->insn);
3850e4b17023SJohn Marino 		  spill_deleted++;
3851e4b17023SJohn Marino 		  insn_info->insn = NULL;
3852e4b17023SJohn Marino 		}
3853e4b17023SJohn Marino 	    }
3854e4b17023SJohn Marino 
3855e4b17023SJohn Marino 	  if (insn_info->insn
3856e4b17023SJohn Marino 	      && INSN_P (insn_info->insn)
3857e4b17023SJohn Marino 	      && (!deleted))
3858e4b17023SJohn Marino 	    {
3859e4b17023SJohn Marino 	      scan_stores_spill (insn_info->store_rec, v, NULL);
3860e4b17023SJohn Marino 	      scan_reads_spill (insn_info->read_rec, v, NULL);
3861e4b17023SJohn Marino 	    }
3862e4b17023SJohn Marino 
3863e4b17023SJohn Marino 	  insn_info = insn_info->prev_insn;
3864e4b17023SJohn Marino 	}
3865e4b17023SJohn Marino     }
3866e4b17023SJohn Marino }
3867e4b17023SJohn Marino 
3868e4b17023SJohn Marino 
3869e4b17023SJohn Marino 
3870e4b17023SJohn Marino /*----------------------------------------------------------------------------
3871e4b17023SJohn Marino    Sixth step.
3872e4b17023SJohn Marino 
3873e4b17023SJohn Marino    Delete stores made redundant by earlier stores (which store the same
3874e4b17023SJohn Marino    value) that couldn't be eliminated.
3875e4b17023SJohn Marino ----------------------------------------------------------------------------*/
3876e4b17023SJohn Marino 
3877e4b17023SJohn Marino static void
dse_step6(void)3878e4b17023SJohn Marino dse_step6 (void)
3879e4b17023SJohn Marino {
3880e4b17023SJohn Marino   basic_block bb;
3881e4b17023SJohn Marino 
3882e4b17023SJohn Marino   FOR_ALL_BB (bb)
3883e4b17023SJohn Marino     {
3884e4b17023SJohn Marino       bb_info_t bb_info = bb_table[bb->index];
3885e4b17023SJohn Marino       insn_info_t insn_info = bb_info->last_insn;
3886e4b17023SJohn Marino 
3887e4b17023SJohn Marino       while (insn_info)
3888e4b17023SJohn Marino 	{
3889e4b17023SJohn Marino 	  /* There may have been code deleted by the dce pass run before
3890e4b17023SJohn Marino 	     this phase.  */
3891e4b17023SJohn Marino 	  if (insn_info->insn
3892e4b17023SJohn Marino 	      && INSN_P (insn_info->insn)
3893e4b17023SJohn Marino 	      && !insn_info->cannot_delete)
3894e4b17023SJohn Marino 	    {
3895e4b17023SJohn Marino 	      store_info_t s_info = insn_info->store_rec;
3896e4b17023SJohn Marino 
3897e4b17023SJohn Marino 	      while (s_info && !s_info->is_set)
3898e4b17023SJohn Marino 		s_info = s_info->next;
3899e4b17023SJohn Marino 	      if (s_info
3900e4b17023SJohn Marino 		  && s_info->redundant_reason
3901e4b17023SJohn Marino 		  && s_info->redundant_reason->insn
3902e4b17023SJohn Marino 		  && INSN_P (s_info->redundant_reason->insn))
3903e4b17023SJohn Marino 		{
3904e4b17023SJohn Marino 		  rtx rinsn = s_info->redundant_reason->insn;
3905e4b17023SJohn Marino 		  if (dump_file)
3906e4b17023SJohn Marino 		    fprintf (dump_file, "Locally deleting insn %d "
3907e4b17023SJohn Marino 					"because insn %d stores the "
3908e4b17023SJohn Marino 					"same value and couldn't be "
3909e4b17023SJohn Marino 					"eliminated\n",
3910e4b17023SJohn Marino 					INSN_UID (insn_info->insn),
3911e4b17023SJohn Marino 					INSN_UID (rinsn));
3912e4b17023SJohn Marino 		  delete_dead_store_insn (insn_info);
3913e4b17023SJohn Marino 		}
3914e4b17023SJohn Marino 	    }
3915e4b17023SJohn Marino 	  insn_info = insn_info->prev_insn;
3916e4b17023SJohn Marino 	}
3917e4b17023SJohn Marino     }
3918e4b17023SJohn Marino }
3919e4b17023SJohn Marino 
3920e4b17023SJohn Marino /*----------------------------------------------------------------------------
3921e4b17023SJohn Marino    Seventh step.
3922e4b17023SJohn Marino 
3923e4b17023SJohn Marino    Destroy everything left standing.
3924e4b17023SJohn Marino ----------------------------------------------------------------------------*/
3925e4b17023SJohn Marino 
3926e4b17023SJohn Marino static void
dse_step7(bool global_done)3927e4b17023SJohn Marino dse_step7 (bool global_done)
3928e4b17023SJohn Marino {
3929e4b17023SJohn Marino   unsigned int i;
3930e4b17023SJohn Marino   group_info_t group;
3931e4b17023SJohn Marino   basic_block bb;
3932e4b17023SJohn Marino 
3933e4b17023SJohn Marino   FOR_EACH_VEC_ELT (group_info_t, rtx_group_vec, i, group)
3934e4b17023SJohn Marino     {
3935e4b17023SJohn Marino       free (group->offset_map_n);
3936e4b17023SJohn Marino       free (group->offset_map_p);
3937e4b17023SJohn Marino       BITMAP_FREE (group->store1_n);
3938e4b17023SJohn Marino       BITMAP_FREE (group->store1_p);
3939e4b17023SJohn Marino       BITMAP_FREE (group->store2_n);
3940e4b17023SJohn Marino       BITMAP_FREE (group->store2_p);
3941e4b17023SJohn Marino       BITMAP_FREE (group->escaped_n);
3942e4b17023SJohn Marino       BITMAP_FREE (group->escaped_p);
3943e4b17023SJohn Marino       BITMAP_FREE (group->group_kill);
3944e4b17023SJohn Marino     }
3945e4b17023SJohn Marino 
3946e4b17023SJohn Marino   if (global_done)
3947e4b17023SJohn Marino     FOR_ALL_BB (bb)
3948e4b17023SJohn Marino       {
3949e4b17023SJohn Marino 	bb_info_t bb_info = bb_table[bb->index];
3950e4b17023SJohn Marino 	BITMAP_FREE (bb_info->gen);
3951e4b17023SJohn Marino 	if (bb_info->kill)
3952e4b17023SJohn Marino 	  BITMAP_FREE (bb_info->kill);
3953e4b17023SJohn Marino 	if (bb_info->in)
3954e4b17023SJohn Marino 	  BITMAP_FREE (bb_info->in);
3955e4b17023SJohn Marino 	if (bb_info->out)
3956e4b17023SJohn Marino 	  BITMAP_FREE (bb_info->out);
3957e4b17023SJohn Marino       }
3958e4b17023SJohn Marino 
3959e4b17023SJohn Marino   if (clear_alias_sets)
3960e4b17023SJohn Marino     {
3961e4b17023SJohn Marino       BITMAP_FREE (clear_alias_sets);
3962e4b17023SJohn Marino       BITMAP_FREE (disqualified_clear_alias_sets);
3963e4b17023SJohn Marino       free_alloc_pool (clear_alias_mode_pool);
3964e4b17023SJohn Marino       htab_delete (clear_alias_mode_table);
3965e4b17023SJohn Marino     }
3966e4b17023SJohn Marino 
3967e4b17023SJohn Marino   end_alias_analysis ();
3968e4b17023SJohn Marino   free (bb_table);
3969e4b17023SJohn Marino   htab_delete (rtx_group_table);
3970e4b17023SJohn Marino   VEC_free (group_info_t, heap, rtx_group_vec);
3971e4b17023SJohn Marino   BITMAP_FREE (all_blocks);
3972e4b17023SJohn Marino   BITMAP_FREE (scratch);
3973e4b17023SJohn Marino   BITMAP_FREE (kill_on_calls);
3974e4b17023SJohn Marino 
3975e4b17023SJohn Marino   free_alloc_pool (rtx_store_info_pool);
3976e4b17023SJohn Marino   free_alloc_pool (read_info_pool);
3977e4b17023SJohn Marino   free_alloc_pool (insn_info_pool);
3978e4b17023SJohn Marino   free_alloc_pool (bb_info_pool);
3979e4b17023SJohn Marino   free_alloc_pool (rtx_group_info_pool);
3980e4b17023SJohn Marino   free_alloc_pool (deferred_change_pool);
3981e4b17023SJohn Marino }
3982e4b17023SJohn Marino 
3983e4b17023SJohn Marino 
3984e4b17023SJohn Marino /* -------------------------------------------------------------------------
3985e4b17023SJohn Marino    DSE
3986e4b17023SJohn Marino    ------------------------------------------------------------------------- */
3987e4b17023SJohn Marino 
3988e4b17023SJohn Marino /* Callback for running pass_rtl_dse.  */
3989e4b17023SJohn Marino 
3990e4b17023SJohn Marino static unsigned int
rest_of_handle_dse(void)3991e4b17023SJohn Marino rest_of_handle_dse (void)
3992e4b17023SJohn Marino {
3993e4b17023SJohn Marino   bool did_global = false;
3994e4b17023SJohn Marino 
3995e4b17023SJohn Marino   df_set_flags (DF_DEFER_INSN_RESCAN);
3996e4b17023SJohn Marino 
3997e4b17023SJohn Marino   /* Need the notes since we must track live hardregs in the forwards
3998e4b17023SJohn Marino      direction.  */
3999e4b17023SJohn Marino   df_note_add_problem ();
4000e4b17023SJohn Marino   df_analyze ();
4001e4b17023SJohn Marino 
4002e4b17023SJohn Marino   dse_step0 ();
4003e4b17023SJohn Marino   dse_step1 ();
4004e4b17023SJohn Marino   dse_step2_init ();
4005e4b17023SJohn Marino   if (dse_step2_nospill ())
4006e4b17023SJohn Marino     {
4007e4b17023SJohn Marino       df_set_flags (DF_LR_RUN_DCE);
4008e4b17023SJohn Marino       df_analyze ();
4009e4b17023SJohn Marino       did_global = true;
4010e4b17023SJohn Marino       if (dump_file)
4011e4b17023SJohn Marino 	fprintf (dump_file, "doing global processing\n");
4012e4b17023SJohn Marino       dse_step3 (false);
4013e4b17023SJohn Marino       dse_step4 ();
4014e4b17023SJohn Marino       dse_step5_nospill ();
4015e4b17023SJohn Marino     }
4016e4b17023SJohn Marino 
4017e4b17023SJohn Marino   /* For the instance of dse that runs after reload, we make a special
4018e4b17023SJohn Marino      pass to process the spills.  These are special in that they are
4019e4b17023SJohn Marino      totally transparent, i.e, there is no aliasing issues that need
4020e4b17023SJohn Marino      to be considered.  This means that the wild reads that kill
4021e4b17023SJohn Marino      everything else do not apply here.  */
4022e4b17023SJohn Marino   if (clear_alias_sets && dse_step2_spill ())
4023e4b17023SJohn Marino     {
4024e4b17023SJohn Marino       if (!did_global)
4025e4b17023SJohn Marino 	{
4026e4b17023SJohn Marino 	  df_set_flags (DF_LR_RUN_DCE);
4027e4b17023SJohn Marino 	  df_analyze ();
4028e4b17023SJohn Marino 	}
4029e4b17023SJohn Marino       did_global = true;
4030e4b17023SJohn Marino       if (dump_file)
4031e4b17023SJohn Marino 	fprintf (dump_file, "doing global spill processing\n");
4032e4b17023SJohn Marino       dse_step3 (true);
4033e4b17023SJohn Marino       dse_step4 ();
4034e4b17023SJohn Marino       dse_step5_spill ();
4035e4b17023SJohn Marino     }
4036e4b17023SJohn Marino 
4037e4b17023SJohn Marino   dse_step6 ();
4038e4b17023SJohn Marino   dse_step7 (did_global);
4039e4b17023SJohn Marino 
4040e4b17023SJohn Marino   if (dump_file)
4041e4b17023SJohn Marino     fprintf (dump_file, "dse: local deletions = %d, global deletions = %d, spill deletions = %d\n",
4042e4b17023SJohn Marino 	     locally_deleted, globally_deleted, spill_deleted);
4043e4b17023SJohn Marino   return 0;
4044e4b17023SJohn Marino }
4045e4b17023SJohn Marino 
4046e4b17023SJohn Marino static bool
gate_dse(void)4047e4b17023SJohn Marino gate_dse (void)
4048e4b17023SJohn Marino {
4049e4b17023SJohn Marino   return gate_dse1 () || gate_dse2 ();
4050e4b17023SJohn Marino }
4051e4b17023SJohn Marino 
4052e4b17023SJohn Marino static bool
gate_dse1(void)4053e4b17023SJohn Marino gate_dse1 (void)
4054e4b17023SJohn Marino {
4055e4b17023SJohn Marino   return optimize > 0 && flag_dse
4056e4b17023SJohn Marino     && dbg_cnt (dse1);
4057e4b17023SJohn Marino }
4058e4b17023SJohn Marino 
4059e4b17023SJohn Marino static bool
gate_dse2(void)4060e4b17023SJohn Marino gate_dse2 (void)
4061e4b17023SJohn Marino {
4062e4b17023SJohn Marino   return optimize > 0 && flag_dse
4063e4b17023SJohn Marino     && dbg_cnt (dse2);
4064e4b17023SJohn Marino }
4065e4b17023SJohn Marino 
4066e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_dse1 =
4067e4b17023SJohn Marino {
4068e4b17023SJohn Marino  {
4069e4b17023SJohn Marino   RTL_PASS,
4070e4b17023SJohn Marino   "dse1",                               /* name */
4071e4b17023SJohn Marino   gate_dse1,                            /* gate */
4072e4b17023SJohn Marino   rest_of_handle_dse,                   /* execute */
4073e4b17023SJohn Marino   NULL,                                 /* sub */
4074e4b17023SJohn Marino   NULL,                                 /* next */
4075e4b17023SJohn Marino   0,                                    /* static_pass_number */
4076e4b17023SJohn Marino   TV_DSE1,                              /* tv_id */
4077e4b17023SJohn Marino   0,                                    /* properties_required */
4078e4b17023SJohn Marino   0,                                    /* properties_provided */
4079e4b17023SJohn Marino   0,                                    /* properties_destroyed */
4080e4b17023SJohn Marino   0,                                    /* todo_flags_start */
4081e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing |
4082e4b17023SJohn Marino   TODO_ggc_collect                      /* todo_flags_finish */
4083e4b17023SJohn Marino  }
4084e4b17023SJohn Marino };
4085e4b17023SJohn Marino 
4086e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_dse2 =
4087e4b17023SJohn Marino {
4088e4b17023SJohn Marino  {
4089e4b17023SJohn Marino   RTL_PASS,
4090e4b17023SJohn Marino   "dse2",                               /* name */
4091e4b17023SJohn Marino   gate_dse2,                            /* gate */
4092e4b17023SJohn Marino   rest_of_handle_dse,                   /* execute */
4093e4b17023SJohn Marino   NULL,                                 /* sub */
4094e4b17023SJohn Marino   NULL,                                 /* next */
4095e4b17023SJohn Marino   0,                                    /* static_pass_number */
4096e4b17023SJohn Marino   TV_DSE2,                              /* tv_id */
4097e4b17023SJohn Marino   0,                                    /* properties_required */
4098e4b17023SJohn Marino   0,                                    /* properties_provided */
4099e4b17023SJohn Marino   0,                                    /* properties_destroyed */
4100e4b17023SJohn Marino   0,                                    /* todo_flags_start */
4101e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing |
4102e4b17023SJohn Marino   TODO_ggc_collect                      /* todo_flags_finish */
4103e4b17023SJohn Marino  }
4104e4b17023SJohn Marino };
4105