xref: /dflybsd-src/contrib/gcc-4.7/gcc/cprop.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Global constant/copy propagation for RTL.
2*e4b17023SJohn Marino    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3*e4b17023SJohn Marino    2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
8*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
9*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
10*e4b17023SJohn Marino version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*e4b17023SJohn Marino for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "diagnostic-core.h"
26*e4b17023SJohn Marino #include "toplev.h"
27*e4b17023SJohn Marino 
28*e4b17023SJohn Marino #include "rtl.h"
29*e4b17023SJohn Marino #include "tree.h"
30*e4b17023SJohn Marino #include "tm_p.h"
31*e4b17023SJohn Marino #include "regs.h"
32*e4b17023SJohn Marino #include "hard-reg-set.h"
33*e4b17023SJohn Marino #include "flags.h"
34*e4b17023SJohn Marino #include "insn-config.h"
35*e4b17023SJohn Marino #include "recog.h"
36*e4b17023SJohn Marino #include "basic-block.h"
37*e4b17023SJohn Marino #include "output.h"
38*e4b17023SJohn Marino #include "function.h"
39*e4b17023SJohn Marino #include "expr.h"
40*e4b17023SJohn Marino #include "except.h"
41*e4b17023SJohn Marino #include "params.h"
42*e4b17023SJohn Marino #include "cselib.h"
43*e4b17023SJohn Marino #include "intl.h"
44*e4b17023SJohn Marino #include "obstack.h"
45*e4b17023SJohn Marino #include "timevar.h"
46*e4b17023SJohn Marino #include "tree-pass.h"
47*e4b17023SJohn Marino #include "hashtab.h"
48*e4b17023SJohn Marino #include "df.h"
49*e4b17023SJohn Marino #include "dbgcnt.h"
50*e4b17023SJohn Marino #include "target.h"
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino /* An obstack for our working variables.  */
54*e4b17023SJohn Marino static struct obstack cprop_obstack;
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino /* Occurrence of an expression.
57*e4b17023SJohn Marino    There is one per basic block.  If a pattern appears more than once the
58*e4b17023SJohn Marino    last appearance is used.  */
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino struct occr
61*e4b17023SJohn Marino {
62*e4b17023SJohn Marino   /* Next occurrence of this expression.  */
63*e4b17023SJohn Marino   struct occr *next;
64*e4b17023SJohn Marino   /* The insn that computes the expression.  */
65*e4b17023SJohn Marino   rtx insn;
66*e4b17023SJohn Marino };
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino typedef struct occr *occr_t;
69*e4b17023SJohn Marino DEF_VEC_P (occr_t);
70*e4b17023SJohn Marino DEF_VEC_ALLOC_P (occr_t, heap);
71*e4b17023SJohn Marino 
72*e4b17023SJohn Marino /* Hash table entry for assignment expressions.  */
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino struct expr
75*e4b17023SJohn Marino {
76*e4b17023SJohn Marino   /* The expression (DEST := SRC).  */
77*e4b17023SJohn Marino   rtx dest;
78*e4b17023SJohn Marino   rtx src;
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino   /* Index in the available expression bitmaps.  */
81*e4b17023SJohn Marino   int bitmap_index;
82*e4b17023SJohn Marino   /* Next entry with the same hash.  */
83*e4b17023SJohn Marino   struct expr *next_same_hash;
84*e4b17023SJohn Marino   /* List of available occurrence in basic blocks in the function.
85*e4b17023SJohn Marino      An "available occurrence" is one that is the last occurrence in the
86*e4b17023SJohn Marino      basic block and whose operands are not modified by following statements
87*e4b17023SJohn Marino      in the basic block [including this insn].  */
88*e4b17023SJohn Marino   struct occr *avail_occr;
89*e4b17023SJohn Marino };
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino /* Hash table for copy propagation expressions.
92*e4b17023SJohn Marino    Each hash table is an array of buckets.
93*e4b17023SJohn Marino    ??? It is known that if it were an array of entries, structure elements
94*e4b17023SJohn Marino    `next_same_hash' and `bitmap_index' wouldn't be necessary.  However, it is
95*e4b17023SJohn Marino    not clear whether in the final analysis a sufficient amount of memory would
96*e4b17023SJohn Marino    be saved as the size of the available expression bitmaps would be larger
97*e4b17023SJohn Marino    [one could build a mapping table without holes afterwards though].
98*e4b17023SJohn Marino    Someday I'll perform the computation and figure it out.  */
99*e4b17023SJohn Marino 
100*e4b17023SJohn Marino struct hash_table_d
101*e4b17023SJohn Marino {
102*e4b17023SJohn Marino   /* The table itself.
103*e4b17023SJohn Marino      This is an array of `set_hash_table_size' elements.  */
104*e4b17023SJohn Marino   struct expr **table;
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino   /* Size of the hash table, in elements.  */
107*e4b17023SJohn Marino   unsigned int size;
108*e4b17023SJohn Marino 
109*e4b17023SJohn Marino   /* Number of hash table elements.  */
110*e4b17023SJohn Marino   unsigned int n_elems;
111*e4b17023SJohn Marino };
112*e4b17023SJohn Marino 
113*e4b17023SJohn Marino /* Copy propagation hash table.  */
114*e4b17023SJohn Marino static struct hash_table_d set_hash_table;
115*e4b17023SJohn Marino 
116*e4b17023SJohn Marino /* Array of implicit set patterns indexed by basic block index.  */
117*e4b17023SJohn Marino static rtx *implicit_sets;
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino /* Array of indexes of expressions for implicit set patterns indexed by basic
120*e4b17023SJohn Marino    block index.  In other words, implicit_set_indexes[i] is the bitmap_index
121*e4b17023SJohn Marino    of the expression whose RTX is implicit_sets[i].  */
122*e4b17023SJohn Marino static int *implicit_set_indexes;
123*e4b17023SJohn Marino 
124*e4b17023SJohn Marino /* Bitmap containing one bit for each register in the program.
125*e4b17023SJohn Marino    Used when performing GCSE to track which registers have been set since
126*e4b17023SJohn Marino    the start or end of the basic block while traversing that block.  */
127*e4b17023SJohn Marino static regset reg_set_bitmap;
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino /* Various variables for statistics gathering.  */
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino /* Memory used in a pass.
132*e4b17023SJohn Marino    This isn't intended to be absolutely precise.  Its intent is only
133*e4b17023SJohn Marino    to keep an eye on memory usage.  */
134*e4b17023SJohn Marino static int bytes_used;
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino /* Number of local constants propagated.  */
137*e4b17023SJohn Marino static int local_const_prop_count;
138*e4b17023SJohn Marino /* Number of local copies propagated.  */
139*e4b17023SJohn Marino static int local_copy_prop_count;
140*e4b17023SJohn Marino /* Number of global constants propagated.  */
141*e4b17023SJohn Marino static int global_const_prop_count;
142*e4b17023SJohn Marino /* Number of global copies propagated.  */
143*e4b17023SJohn Marino static int global_copy_prop_count;
144*e4b17023SJohn Marino 
145*e4b17023SJohn Marino #define GOBNEW(T)		((T *) cprop_alloc (sizeof (T)))
146*e4b17023SJohn Marino #define GOBNEWVAR(T, S)		((T *) cprop_alloc ((S)))
147*e4b17023SJohn Marino 
148*e4b17023SJohn Marino /* Cover function to obstack_alloc.  */
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino static void *
cprop_alloc(unsigned long size)151*e4b17023SJohn Marino cprop_alloc (unsigned long size)
152*e4b17023SJohn Marino {
153*e4b17023SJohn Marino   bytes_used += size;
154*e4b17023SJohn Marino   return obstack_alloc (&cprop_obstack, size);
155*e4b17023SJohn Marino }
156*e4b17023SJohn Marino 
157*e4b17023SJohn Marino /* Return nonzero if register X is unchanged from INSN to the end
158*e4b17023SJohn Marino    of INSN's basic block.  */
159*e4b17023SJohn Marino 
160*e4b17023SJohn Marino static int
reg_available_p(const_rtx x,const_rtx insn ATTRIBUTE_UNUSED)161*e4b17023SJohn Marino reg_available_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
162*e4b17023SJohn Marino {
163*e4b17023SJohn Marino   return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
164*e4b17023SJohn Marino }
165*e4b17023SJohn Marino 
166*e4b17023SJohn Marino /* Hash a set of register REGNO.
167*e4b17023SJohn Marino 
168*e4b17023SJohn Marino    Sets are hashed on the register that is set.  This simplifies the PRE copy
169*e4b17023SJohn Marino    propagation code.
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino    ??? May need to make things more elaborate.  Later, as necessary.  */
172*e4b17023SJohn Marino 
173*e4b17023SJohn Marino static unsigned int
hash_set(int regno,int hash_table_size)174*e4b17023SJohn Marino hash_set (int regno, int hash_table_size)
175*e4b17023SJohn Marino {
176*e4b17023SJohn Marino   unsigned int hash;
177*e4b17023SJohn Marino 
178*e4b17023SJohn Marino   hash = regno;
179*e4b17023SJohn Marino   return hash % hash_table_size;
180*e4b17023SJohn Marino }
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino /* Insert assignment DEST:=SET from INSN in the hash table.
183*e4b17023SJohn Marino    DEST is a register and SET is a register or a suitable constant.
184*e4b17023SJohn Marino    If the assignment is already present in the table, record it as
185*e4b17023SJohn Marino    the last occurrence in INSN's basic block.
186*e4b17023SJohn Marino    IMPLICIT is true if it's an implicit set, false otherwise.  */
187*e4b17023SJohn Marino 
188*e4b17023SJohn Marino static void
insert_set_in_table(rtx dest,rtx src,rtx insn,struct hash_table_d * table,bool implicit)189*e4b17023SJohn Marino insert_set_in_table (rtx dest, rtx src, rtx insn, struct hash_table_d *table,
190*e4b17023SJohn Marino 		     bool implicit)
191*e4b17023SJohn Marino {
192*e4b17023SJohn Marino   bool found = false;
193*e4b17023SJohn Marino   unsigned int hash;
194*e4b17023SJohn Marino   struct expr *cur_expr, *last_expr = NULL;
195*e4b17023SJohn Marino   struct occr *cur_occr;
196*e4b17023SJohn Marino 
197*e4b17023SJohn Marino   hash = hash_set (REGNO (dest), table->size);
198*e4b17023SJohn Marino 
199*e4b17023SJohn Marino   for (cur_expr = table->table[hash]; cur_expr;
200*e4b17023SJohn Marino        cur_expr = cur_expr->next_same_hash)
201*e4b17023SJohn Marino     {
202*e4b17023SJohn Marino       if (dest == cur_expr->dest
203*e4b17023SJohn Marino 	  && src == cur_expr->src)
204*e4b17023SJohn Marino 	{
205*e4b17023SJohn Marino 	  found = true;
206*e4b17023SJohn Marino 	  break;
207*e4b17023SJohn Marino 	}
208*e4b17023SJohn Marino       last_expr = cur_expr;
209*e4b17023SJohn Marino     }
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino   if (! found)
212*e4b17023SJohn Marino     {
213*e4b17023SJohn Marino       cur_expr = GOBNEW (struct expr);
214*e4b17023SJohn Marino       bytes_used += sizeof (struct expr);
215*e4b17023SJohn Marino       if (table->table[hash] == NULL)
216*e4b17023SJohn Marino 	/* This is the first pattern that hashed to this index.  */
217*e4b17023SJohn Marino 	table->table[hash] = cur_expr;
218*e4b17023SJohn Marino       else
219*e4b17023SJohn Marino 	/* Add EXPR to end of this hash chain.  */
220*e4b17023SJohn Marino 	last_expr->next_same_hash = cur_expr;
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino       /* Set the fields of the expr element.
223*e4b17023SJohn Marino 	 We must copy X because it can be modified when copy propagation is
224*e4b17023SJohn Marino 	 performed on its operands.  */
225*e4b17023SJohn Marino       cur_expr->dest = copy_rtx (dest);
226*e4b17023SJohn Marino       cur_expr->src = copy_rtx (src);
227*e4b17023SJohn Marino       cur_expr->bitmap_index = table->n_elems++;
228*e4b17023SJohn Marino       cur_expr->next_same_hash = NULL;
229*e4b17023SJohn Marino       cur_expr->avail_occr = NULL;
230*e4b17023SJohn Marino     }
231*e4b17023SJohn Marino 
232*e4b17023SJohn Marino   /* Now record the occurrence.  */
233*e4b17023SJohn Marino   cur_occr = cur_expr->avail_occr;
234*e4b17023SJohn Marino 
235*e4b17023SJohn Marino   if (cur_occr
236*e4b17023SJohn Marino       && BLOCK_FOR_INSN (cur_occr->insn) == BLOCK_FOR_INSN (insn))
237*e4b17023SJohn Marino     {
238*e4b17023SJohn Marino       /* Found another instance of the expression in the same basic block.
239*e4b17023SJohn Marino 	 Prefer this occurrence to the currently recorded one.  We want
240*e4b17023SJohn Marino 	 the last one in the block and the block is scanned from start
241*e4b17023SJohn Marino 	 to end.  */
242*e4b17023SJohn Marino       cur_occr->insn = insn;
243*e4b17023SJohn Marino     }
244*e4b17023SJohn Marino   else
245*e4b17023SJohn Marino     {
246*e4b17023SJohn Marino       /* First occurrence of this expression in this basic block.  */
247*e4b17023SJohn Marino       cur_occr = GOBNEW (struct occr);
248*e4b17023SJohn Marino       bytes_used += sizeof (struct occr);
249*e4b17023SJohn Marino       cur_occr->insn = insn;
250*e4b17023SJohn Marino       cur_occr->next = cur_expr->avail_occr;
251*e4b17023SJohn Marino       cur_expr->avail_occr = cur_occr;
252*e4b17023SJohn Marino     }
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino   /* Record bitmap_index of the implicit set in implicit_set_indexes.  */
255*e4b17023SJohn Marino   if (implicit)
256*e4b17023SJohn Marino     implicit_set_indexes[BLOCK_FOR_INSN(insn)->index] = cur_expr->bitmap_index;
257*e4b17023SJohn Marino }
258*e4b17023SJohn Marino 
259*e4b17023SJohn Marino /* Determine whether the rtx X should be treated as a constant for CPROP.
260*e4b17023SJohn Marino    Since X might be inserted more than once we have to take care that it
261*e4b17023SJohn Marino    is sharable.  */
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino static bool
cprop_constant_p(const_rtx x)264*e4b17023SJohn Marino cprop_constant_p (const_rtx x)
265*e4b17023SJohn Marino {
266*e4b17023SJohn Marino   return CONSTANT_P (x) && (GET_CODE (x) != CONST || shared_const_p (x));
267*e4b17023SJohn Marino }
268*e4b17023SJohn Marino 
269*e4b17023SJohn Marino /* Scan SET present in INSN and add an entry to the hash TABLE.
270*e4b17023SJohn Marino    IMPLICIT is true if it's an implicit set, false otherwise.  */
271*e4b17023SJohn Marino 
272*e4b17023SJohn Marino static void
hash_scan_set(rtx set,rtx insn,struct hash_table_d * table,bool implicit)273*e4b17023SJohn Marino hash_scan_set (rtx set, rtx insn, struct hash_table_d *table, bool implicit)
274*e4b17023SJohn Marino {
275*e4b17023SJohn Marino   rtx src = SET_SRC (set);
276*e4b17023SJohn Marino   rtx dest = SET_DEST (set);
277*e4b17023SJohn Marino 
278*e4b17023SJohn Marino   if (REG_P (dest)
279*e4b17023SJohn Marino       && ! HARD_REGISTER_P (dest)
280*e4b17023SJohn Marino       && reg_available_p (dest, insn)
281*e4b17023SJohn Marino       && can_copy_p (GET_MODE (dest)))
282*e4b17023SJohn Marino     {
283*e4b17023SJohn Marino       /* See if a REG_EQUAL note shows this equivalent to a simpler expression.
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino 	 This allows us to do a single CPROP pass and still eliminate
286*e4b17023SJohn Marino 	 redundant constants, addresses or other expressions that are
287*e4b17023SJohn Marino 	 constructed with multiple instructions.
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino 	 However, keep the original SRC if INSN is a simple reg-reg move.  In
290*e4b17023SJohn Marino 	 In this case, there will almost always be a REG_EQUAL note on the
291*e4b17023SJohn Marino 	 insn that sets SRC.  By recording the REG_EQUAL value here as SRC
292*e4b17023SJohn Marino 	 for INSN, we miss copy propagation opportunities.
293*e4b17023SJohn Marino 
294*e4b17023SJohn Marino 	 Note that this does not impede profitable constant propagations.  We
295*e4b17023SJohn Marino 	 "look through" reg-reg sets in lookup_set.  */
296*e4b17023SJohn Marino       rtx note = find_reg_equal_equiv_note (insn);
297*e4b17023SJohn Marino       if (note != 0
298*e4b17023SJohn Marino 	  && REG_NOTE_KIND (note) == REG_EQUAL
299*e4b17023SJohn Marino 	  && !REG_P (src)
300*e4b17023SJohn Marino 	  && cprop_constant_p (XEXP (note, 0)))
301*e4b17023SJohn Marino 	src = XEXP (note, 0), set = gen_rtx_SET (VOIDmode, dest, src);
302*e4b17023SJohn Marino 
303*e4b17023SJohn Marino       /* Record sets for constant/copy propagation.  */
304*e4b17023SJohn Marino       if ((REG_P (src)
305*e4b17023SJohn Marino 	   && src != dest
306*e4b17023SJohn Marino 	   && ! HARD_REGISTER_P (src)
307*e4b17023SJohn Marino 	   && reg_available_p (src, insn))
308*e4b17023SJohn Marino 	  || cprop_constant_p (src))
309*e4b17023SJohn Marino 	insert_set_in_table (dest, src, insn, table, implicit);
310*e4b17023SJohn Marino     }
311*e4b17023SJohn Marino }
312*e4b17023SJohn Marino 
313*e4b17023SJohn Marino /* Process INSN and add hash table entries as appropriate.  */
314*e4b17023SJohn Marino 
315*e4b17023SJohn Marino static void
hash_scan_insn(rtx insn,struct hash_table_d * table)316*e4b17023SJohn Marino hash_scan_insn (rtx insn, struct hash_table_d *table)
317*e4b17023SJohn Marino {
318*e4b17023SJohn Marino   rtx pat = PATTERN (insn);
319*e4b17023SJohn Marino   int i;
320*e4b17023SJohn Marino 
321*e4b17023SJohn Marino   /* Pick out the sets of INSN and for other forms of instructions record
322*e4b17023SJohn Marino      what's been modified.  */
323*e4b17023SJohn Marino 
324*e4b17023SJohn Marino   if (GET_CODE (pat) == SET)
325*e4b17023SJohn Marino     hash_scan_set (pat, insn, table, false);
326*e4b17023SJohn Marino   else if (GET_CODE (pat) == PARALLEL)
327*e4b17023SJohn Marino     for (i = 0; i < XVECLEN (pat, 0); i++)
328*e4b17023SJohn Marino       {
329*e4b17023SJohn Marino 	rtx x = XVECEXP (pat, 0, i);
330*e4b17023SJohn Marino 
331*e4b17023SJohn Marino 	if (GET_CODE (x) == SET)
332*e4b17023SJohn Marino 	  hash_scan_set (x, insn, table, false);
333*e4b17023SJohn Marino       }
334*e4b17023SJohn Marino }
335*e4b17023SJohn Marino 
336*e4b17023SJohn Marino /* Dump the hash table TABLE to file FILE under the name NAME.  */
337*e4b17023SJohn Marino 
338*e4b17023SJohn Marino static void
dump_hash_table(FILE * file,const char * name,struct hash_table_d * table)339*e4b17023SJohn Marino dump_hash_table (FILE *file, const char *name, struct hash_table_d *table)
340*e4b17023SJohn Marino {
341*e4b17023SJohn Marino   int i;
342*e4b17023SJohn Marino   /* Flattened out table, so it's printed in proper order.  */
343*e4b17023SJohn Marino   struct expr **flat_table;
344*e4b17023SJohn Marino   unsigned int *hash_val;
345*e4b17023SJohn Marino   struct expr *expr;
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino   flat_table = XCNEWVEC (struct expr *, table->n_elems);
348*e4b17023SJohn Marino   hash_val = XNEWVEC (unsigned int, table->n_elems);
349*e4b17023SJohn Marino 
350*e4b17023SJohn Marino   for (i = 0; i < (int) table->size; i++)
351*e4b17023SJohn Marino     for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
352*e4b17023SJohn Marino       {
353*e4b17023SJohn Marino 	flat_table[expr->bitmap_index] = expr;
354*e4b17023SJohn Marino 	hash_val[expr->bitmap_index] = i;
355*e4b17023SJohn Marino       }
356*e4b17023SJohn Marino 
357*e4b17023SJohn Marino   fprintf (file, "%s hash table (%d buckets, %d entries)\n",
358*e4b17023SJohn Marino 	   name, table->size, table->n_elems);
359*e4b17023SJohn Marino 
360*e4b17023SJohn Marino   for (i = 0; i < (int) table->n_elems; i++)
361*e4b17023SJohn Marino     if (flat_table[i] != 0)
362*e4b17023SJohn Marino       {
363*e4b17023SJohn Marino 	expr = flat_table[i];
364*e4b17023SJohn Marino 	fprintf (file, "Index %d (hash value %d)\n  ",
365*e4b17023SJohn Marino 		 expr->bitmap_index, hash_val[i]);
366*e4b17023SJohn Marino 	print_rtl (file, expr->dest);
367*e4b17023SJohn Marino 	fprintf (file, " := ");
368*e4b17023SJohn Marino 	print_rtl (file, expr->src);
369*e4b17023SJohn Marino 	fprintf (file, "\n");
370*e4b17023SJohn Marino       }
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino   fprintf (file, "\n");
373*e4b17023SJohn Marino 
374*e4b17023SJohn Marino   free (flat_table);
375*e4b17023SJohn Marino   free (hash_val);
376*e4b17023SJohn Marino }
377*e4b17023SJohn Marino 
378*e4b17023SJohn Marino /* Record as unavailable all registers that are DEF operands of INSN.  */
379*e4b17023SJohn Marino 
380*e4b17023SJohn Marino static void
make_set_regs_unavailable(rtx insn)381*e4b17023SJohn Marino make_set_regs_unavailable (rtx insn)
382*e4b17023SJohn Marino {
383*e4b17023SJohn Marino   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
384*e4b17023SJohn Marino   df_ref *def_rec;
385*e4b17023SJohn Marino 
386*e4b17023SJohn Marino   for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
387*e4b17023SJohn Marino     SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (*def_rec));
388*e4b17023SJohn Marino }
389*e4b17023SJohn Marino 
390*e4b17023SJohn Marino /* Top level function to create an assignment hash table.
391*e4b17023SJohn Marino 
392*e4b17023SJohn Marino    Assignment entries are placed in the hash table if
393*e4b17023SJohn Marino    - they are of the form (set (pseudo-reg) src),
394*e4b17023SJohn Marino    - src is something we want to perform const/copy propagation on,
395*e4b17023SJohn Marino    - none of the operands or target are subsequently modified in the block
396*e4b17023SJohn Marino 
397*e4b17023SJohn Marino    Currently src must be a pseudo-reg or a const_int.
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino    TABLE is the table computed.  */
400*e4b17023SJohn Marino 
401*e4b17023SJohn Marino static void
compute_hash_table_work(struct hash_table_d * table)402*e4b17023SJohn Marino compute_hash_table_work (struct hash_table_d *table)
403*e4b17023SJohn Marino {
404*e4b17023SJohn Marino   basic_block bb;
405*e4b17023SJohn Marino 
406*e4b17023SJohn Marino   /* Allocate vars to track sets of regs.  */
407*e4b17023SJohn Marino   reg_set_bitmap = ALLOC_REG_SET (NULL);
408*e4b17023SJohn Marino 
409*e4b17023SJohn Marino   FOR_EACH_BB (bb)
410*e4b17023SJohn Marino     {
411*e4b17023SJohn Marino       rtx insn;
412*e4b17023SJohn Marino 
413*e4b17023SJohn Marino       /* Reset tables used to keep track of what's not yet invalid [since
414*e4b17023SJohn Marino 	 the end of the block].  */
415*e4b17023SJohn Marino       CLEAR_REG_SET (reg_set_bitmap);
416*e4b17023SJohn Marino 
417*e4b17023SJohn Marino       /* Go over all insns from the last to the first.  This is convenient
418*e4b17023SJohn Marino 	 for tracking available registers, i.e. not set between INSN and
419*e4b17023SJohn Marino 	 the end of the basic block BB.  */
420*e4b17023SJohn Marino       FOR_BB_INSNS_REVERSE (bb, insn)
421*e4b17023SJohn Marino         {
422*e4b17023SJohn Marino 	  /* Only real insns are interesting.  */
423*e4b17023SJohn Marino 	  if (!NONDEBUG_INSN_P (insn))
424*e4b17023SJohn Marino 	    continue;
425*e4b17023SJohn Marino 
426*e4b17023SJohn Marino 	  /* Record interesting sets from INSN in the hash table.  */
427*e4b17023SJohn Marino 	  hash_scan_insn (insn, table);
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino 	  /* Any registers set in INSN will make SETs above it not AVAIL.  */
430*e4b17023SJohn Marino 	  make_set_regs_unavailable (insn);
431*e4b17023SJohn Marino 	}
432*e4b17023SJohn Marino 
433*e4b17023SJohn Marino       /* Insert implicit sets in the hash table, pretending they appear as
434*e4b17023SJohn Marino 	 insns at the head of the basic block.  */
435*e4b17023SJohn Marino       if (implicit_sets[bb->index] != NULL_RTX)
436*e4b17023SJohn Marino 	hash_scan_set (implicit_sets[bb->index], BB_HEAD (bb), table, true);
437*e4b17023SJohn Marino     }
438*e4b17023SJohn Marino 
439*e4b17023SJohn Marino   FREE_REG_SET (reg_set_bitmap);
440*e4b17023SJohn Marino }
441*e4b17023SJohn Marino 
442*e4b17023SJohn Marino /* Allocate space for the set/expr hash TABLE.
443*e4b17023SJohn Marino    It is used to determine the number of buckets to use.  */
444*e4b17023SJohn Marino 
445*e4b17023SJohn Marino static void
alloc_hash_table(struct hash_table_d * table)446*e4b17023SJohn Marino alloc_hash_table (struct hash_table_d *table)
447*e4b17023SJohn Marino {
448*e4b17023SJohn Marino   int n;
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino   n = get_max_insn_count ();
451*e4b17023SJohn Marino 
452*e4b17023SJohn Marino   table->size = n / 4;
453*e4b17023SJohn Marino   if (table->size < 11)
454*e4b17023SJohn Marino     table->size = 11;
455*e4b17023SJohn Marino 
456*e4b17023SJohn Marino   /* Attempt to maintain efficient use of hash table.
457*e4b17023SJohn Marino      Making it an odd number is simplest for now.
458*e4b17023SJohn Marino      ??? Later take some measurements.  */
459*e4b17023SJohn Marino   table->size |= 1;
460*e4b17023SJohn Marino   n = table->size * sizeof (struct expr *);
461*e4b17023SJohn Marino   table->table = XNEWVAR (struct expr *, n);
462*e4b17023SJohn Marino }
463*e4b17023SJohn Marino 
464*e4b17023SJohn Marino /* Free things allocated by alloc_hash_table.  */
465*e4b17023SJohn Marino 
466*e4b17023SJohn Marino static void
free_hash_table(struct hash_table_d * table)467*e4b17023SJohn Marino free_hash_table (struct hash_table_d *table)
468*e4b17023SJohn Marino {
469*e4b17023SJohn Marino   free (table->table);
470*e4b17023SJohn Marino }
471*e4b17023SJohn Marino 
472*e4b17023SJohn Marino /* Compute the hash TABLE for doing copy/const propagation or
473*e4b17023SJohn Marino    expression hash table.  */
474*e4b17023SJohn Marino 
475*e4b17023SJohn Marino static void
compute_hash_table(struct hash_table_d * table)476*e4b17023SJohn Marino compute_hash_table (struct hash_table_d *table)
477*e4b17023SJohn Marino {
478*e4b17023SJohn Marino   /* Initialize count of number of entries in hash table.  */
479*e4b17023SJohn Marino   table->n_elems = 0;
480*e4b17023SJohn Marino   memset (table->table, 0, table->size * sizeof (struct expr *));
481*e4b17023SJohn Marino 
482*e4b17023SJohn Marino   compute_hash_table_work (table);
483*e4b17023SJohn Marino }
484*e4b17023SJohn Marino 
485*e4b17023SJohn Marino /* Expression tracking support.  */
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino /* Lookup REGNO in the set TABLE.  The result is a pointer to the
488*e4b17023SJohn Marino    table entry, or NULL if not found.  */
489*e4b17023SJohn Marino 
490*e4b17023SJohn Marino static struct expr *
lookup_set(unsigned int regno,struct hash_table_d * table)491*e4b17023SJohn Marino lookup_set (unsigned int regno, struct hash_table_d *table)
492*e4b17023SJohn Marino {
493*e4b17023SJohn Marino   unsigned int hash = hash_set (regno, table->size);
494*e4b17023SJohn Marino   struct expr *expr;
495*e4b17023SJohn Marino 
496*e4b17023SJohn Marino   expr = table->table[hash];
497*e4b17023SJohn Marino 
498*e4b17023SJohn Marino   while (expr && REGNO (expr->dest) != regno)
499*e4b17023SJohn Marino     expr = expr->next_same_hash;
500*e4b17023SJohn Marino 
501*e4b17023SJohn Marino   return expr;
502*e4b17023SJohn Marino }
503*e4b17023SJohn Marino 
504*e4b17023SJohn Marino /* Return the next entry for REGNO in list EXPR.  */
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino static struct expr *
next_set(unsigned int regno,struct expr * expr)507*e4b17023SJohn Marino next_set (unsigned int regno, struct expr *expr)
508*e4b17023SJohn Marino {
509*e4b17023SJohn Marino   do
510*e4b17023SJohn Marino     expr = expr->next_same_hash;
511*e4b17023SJohn Marino   while (expr && REGNO (expr->dest) != regno);
512*e4b17023SJohn Marino 
513*e4b17023SJohn Marino   return expr;
514*e4b17023SJohn Marino }
515*e4b17023SJohn Marino 
516*e4b17023SJohn Marino /* Reset tables used to keep track of what's still available [since the
517*e4b17023SJohn Marino    start of the block].  */
518*e4b17023SJohn Marino 
519*e4b17023SJohn Marino static void
reset_opr_set_tables(void)520*e4b17023SJohn Marino reset_opr_set_tables (void)
521*e4b17023SJohn Marino {
522*e4b17023SJohn Marino   /* Maintain a bitmap of which regs have been set since beginning of
523*e4b17023SJohn Marino      the block.  */
524*e4b17023SJohn Marino   CLEAR_REG_SET (reg_set_bitmap);
525*e4b17023SJohn Marino }
526*e4b17023SJohn Marino 
527*e4b17023SJohn Marino /* Return nonzero if the register X has not been set yet [since the
528*e4b17023SJohn Marino    start of the basic block containing INSN].  */
529*e4b17023SJohn Marino 
530*e4b17023SJohn Marino static int
reg_not_set_p(const_rtx x,const_rtx insn ATTRIBUTE_UNUSED)531*e4b17023SJohn Marino reg_not_set_p (const_rtx x, const_rtx insn ATTRIBUTE_UNUSED)
532*e4b17023SJohn Marino {
533*e4b17023SJohn Marino   return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x));
534*e4b17023SJohn Marino }
535*e4b17023SJohn Marino 
536*e4b17023SJohn Marino /* Record things set by INSN.
537*e4b17023SJohn Marino    This data is used by reg_not_set_p.  */
538*e4b17023SJohn Marino 
539*e4b17023SJohn Marino static void
mark_oprs_set(rtx insn)540*e4b17023SJohn Marino mark_oprs_set (rtx insn)
541*e4b17023SJohn Marino {
542*e4b17023SJohn Marino   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
543*e4b17023SJohn Marino   df_ref *def_rec;
544*e4b17023SJohn Marino 
545*e4b17023SJohn Marino   for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
546*e4b17023SJohn Marino     SET_REGNO_REG_SET (reg_set_bitmap, DF_REF_REGNO (*def_rec));
547*e4b17023SJohn Marino }
548*e4b17023SJohn Marino 
549*e4b17023SJohn Marino /* Compute copy/constant propagation working variables.  */
550*e4b17023SJohn Marino 
551*e4b17023SJohn Marino /* Local properties of assignments.  */
552*e4b17023SJohn Marino static sbitmap *cprop_avloc;
553*e4b17023SJohn Marino static sbitmap *cprop_kill;
554*e4b17023SJohn Marino 
555*e4b17023SJohn Marino /* Global properties of assignments (computed from the local properties).  */
556*e4b17023SJohn Marino static sbitmap *cprop_avin;
557*e4b17023SJohn Marino static sbitmap *cprop_avout;
558*e4b17023SJohn Marino 
559*e4b17023SJohn Marino /* Allocate vars used for copy/const propagation.  N_BLOCKS is the number of
560*e4b17023SJohn Marino    basic blocks.  N_SETS is the number of sets.  */
561*e4b17023SJohn Marino 
562*e4b17023SJohn Marino static void
alloc_cprop_mem(int n_blocks,int n_sets)563*e4b17023SJohn Marino alloc_cprop_mem (int n_blocks, int n_sets)
564*e4b17023SJohn Marino {
565*e4b17023SJohn Marino   cprop_avloc = sbitmap_vector_alloc (n_blocks, n_sets);
566*e4b17023SJohn Marino   cprop_kill = sbitmap_vector_alloc (n_blocks, n_sets);
567*e4b17023SJohn Marino 
568*e4b17023SJohn Marino   cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets);
569*e4b17023SJohn Marino   cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets);
570*e4b17023SJohn Marino }
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino /* Free vars used by copy/const propagation.  */
573*e4b17023SJohn Marino 
574*e4b17023SJohn Marino static void
free_cprop_mem(void)575*e4b17023SJohn Marino free_cprop_mem (void)
576*e4b17023SJohn Marino {
577*e4b17023SJohn Marino   sbitmap_vector_free (cprop_avloc);
578*e4b17023SJohn Marino   sbitmap_vector_free (cprop_kill);
579*e4b17023SJohn Marino   sbitmap_vector_free (cprop_avin);
580*e4b17023SJohn Marino   sbitmap_vector_free (cprop_avout);
581*e4b17023SJohn Marino }
582*e4b17023SJohn Marino 
583*e4b17023SJohn Marino /* Compute the local properties of each recorded expression.
584*e4b17023SJohn Marino 
585*e4b17023SJohn Marino    Local properties are those that are defined by the block, irrespective of
586*e4b17023SJohn Marino    other blocks.
587*e4b17023SJohn Marino 
588*e4b17023SJohn Marino    An expression is killed in a block if its operands, either DEST or SRC, are
589*e4b17023SJohn Marino    modified in the block.
590*e4b17023SJohn Marino 
591*e4b17023SJohn Marino    An expression is computed (locally available) in a block if it is computed
592*e4b17023SJohn Marino    at least once and expression would contain the same value if the
593*e4b17023SJohn Marino    computation was moved to the end of the block.
594*e4b17023SJohn Marino 
595*e4b17023SJohn Marino    KILL and COMP are destination sbitmaps for recording local properties.  */
596*e4b17023SJohn Marino 
597*e4b17023SJohn Marino static void
compute_local_properties(sbitmap * kill,sbitmap * comp,struct hash_table_d * table)598*e4b17023SJohn Marino compute_local_properties (sbitmap *kill, sbitmap *comp,
599*e4b17023SJohn Marino 			  struct hash_table_d *table)
600*e4b17023SJohn Marino {
601*e4b17023SJohn Marino   unsigned int i;
602*e4b17023SJohn Marino 
603*e4b17023SJohn Marino   /* Initialize the bitmaps that were passed in.  */
604*e4b17023SJohn Marino   sbitmap_vector_zero (kill, last_basic_block);
605*e4b17023SJohn Marino   sbitmap_vector_zero (comp, last_basic_block);
606*e4b17023SJohn Marino 
607*e4b17023SJohn Marino   for (i = 0; i < table->size; i++)
608*e4b17023SJohn Marino     {
609*e4b17023SJohn Marino       struct expr *expr;
610*e4b17023SJohn Marino 
611*e4b17023SJohn Marino       for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash)
612*e4b17023SJohn Marino 	{
613*e4b17023SJohn Marino 	  int indx = expr->bitmap_index;
614*e4b17023SJohn Marino 	  df_ref def;
615*e4b17023SJohn Marino 	  struct occr *occr;
616*e4b17023SJohn Marino 
617*e4b17023SJohn Marino 	  /* For each definition of the destination pseudo-reg, the expression
618*e4b17023SJohn Marino 	     is killed in the block where the definition is.  */
619*e4b17023SJohn Marino 	  for (def = DF_REG_DEF_CHAIN (REGNO (expr->dest));
620*e4b17023SJohn Marino 	       def; def = DF_REF_NEXT_REG (def))
621*e4b17023SJohn Marino 	    SET_BIT (kill[DF_REF_BB (def)->index], indx);
622*e4b17023SJohn Marino 
623*e4b17023SJohn Marino 	  /* If the source is a pseudo-reg, for each definition of the source,
624*e4b17023SJohn Marino 	     the expression is killed in the block where the definition is.  */
625*e4b17023SJohn Marino 	  if (REG_P (expr->src))
626*e4b17023SJohn Marino 	    for (def = DF_REG_DEF_CHAIN (REGNO (expr->src));
627*e4b17023SJohn Marino 		 def; def = DF_REF_NEXT_REG (def))
628*e4b17023SJohn Marino 	      SET_BIT (kill[DF_REF_BB (def)->index], indx);
629*e4b17023SJohn Marino 
630*e4b17023SJohn Marino 	  /* The occurrences recorded in avail_occr are exactly those that
631*e4b17023SJohn Marino 	     are locally available in the block where they are.  */
632*e4b17023SJohn Marino 	  for (occr = expr->avail_occr; occr != NULL; occr = occr->next)
633*e4b17023SJohn Marino 	    {
634*e4b17023SJohn Marino 	      SET_BIT (comp[BLOCK_FOR_INSN (occr->insn)->index], indx);
635*e4b17023SJohn Marino 	    }
636*e4b17023SJohn Marino 	}
637*e4b17023SJohn Marino     }
638*e4b17023SJohn Marino }
639*e4b17023SJohn Marino 
640*e4b17023SJohn Marino /* Hash table support.  */
641*e4b17023SJohn Marino 
642*e4b17023SJohn Marino /* Top level routine to do the dataflow analysis needed by copy/const
643*e4b17023SJohn Marino    propagation.  */
644*e4b17023SJohn Marino 
645*e4b17023SJohn Marino static void
compute_cprop_data(void)646*e4b17023SJohn Marino compute_cprop_data (void)
647*e4b17023SJohn Marino {
648*e4b17023SJohn Marino   basic_block bb;
649*e4b17023SJohn Marino 
650*e4b17023SJohn Marino   compute_local_properties (cprop_kill, cprop_avloc, &set_hash_table);
651*e4b17023SJohn Marino   compute_available (cprop_avloc, cprop_kill, cprop_avout, cprop_avin);
652*e4b17023SJohn Marino 
653*e4b17023SJohn Marino   /* Merge implicit sets into CPROP_AVIN.  They are always available at the
654*e4b17023SJohn Marino      entry of their basic block.  We need to do this because 1) implicit sets
655*e4b17023SJohn Marino      aren't recorded for the local pass so they cannot be propagated within
656*e4b17023SJohn Marino      their basic block by this pass and 2) the global pass would otherwise
657*e4b17023SJohn Marino      propagate them only in the successors of their basic block.  */
658*e4b17023SJohn Marino   FOR_EACH_BB (bb)
659*e4b17023SJohn Marino     {
660*e4b17023SJohn Marino       int index = implicit_set_indexes[bb->index];
661*e4b17023SJohn Marino       if (index != -1)
662*e4b17023SJohn Marino 	SET_BIT (cprop_avin[bb->index], index);
663*e4b17023SJohn Marino     }
664*e4b17023SJohn Marino }
665*e4b17023SJohn Marino 
666*e4b17023SJohn Marino /* Copy/constant propagation.  */
667*e4b17023SJohn Marino 
668*e4b17023SJohn Marino /* Maximum number of register uses in an insn that we handle.  */
669*e4b17023SJohn Marino #define MAX_USES 8
670*e4b17023SJohn Marino 
671*e4b17023SJohn Marino /* Table of uses (registers, both hard and pseudo) found in an insn.
672*e4b17023SJohn Marino    Allocated statically to avoid alloc/free complexity and overhead.  */
673*e4b17023SJohn Marino static rtx reg_use_table[MAX_USES];
674*e4b17023SJohn Marino 
675*e4b17023SJohn Marino /* Index into `reg_use_table' while building it.  */
676*e4b17023SJohn Marino static unsigned reg_use_count;
677*e4b17023SJohn Marino 
678*e4b17023SJohn Marino /* Set up a list of register numbers used in INSN.  The found uses are stored
679*e4b17023SJohn Marino    in `reg_use_table'.  `reg_use_count' is initialized to zero before entry,
680*e4b17023SJohn Marino    and contains the number of uses in the table upon exit.
681*e4b17023SJohn Marino 
682*e4b17023SJohn Marino    ??? If a register appears multiple times we will record it multiple times.
683*e4b17023SJohn Marino    This doesn't hurt anything but it will slow things down.  */
684*e4b17023SJohn Marino 
685*e4b17023SJohn Marino static void
find_used_regs(rtx * xptr,void * data ATTRIBUTE_UNUSED)686*e4b17023SJohn Marino find_used_regs (rtx *xptr, void *data ATTRIBUTE_UNUSED)
687*e4b17023SJohn Marino {
688*e4b17023SJohn Marino   int i, j;
689*e4b17023SJohn Marino   enum rtx_code code;
690*e4b17023SJohn Marino   const char *fmt;
691*e4b17023SJohn Marino   rtx x = *xptr;
692*e4b17023SJohn Marino 
693*e4b17023SJohn Marino   /* repeat is used to turn tail-recursion into iteration since GCC
694*e4b17023SJohn Marino      can't do it when there's no return value.  */
695*e4b17023SJohn Marino  repeat:
696*e4b17023SJohn Marino   if (x == 0)
697*e4b17023SJohn Marino     return;
698*e4b17023SJohn Marino 
699*e4b17023SJohn Marino   code = GET_CODE (x);
700*e4b17023SJohn Marino   if (REG_P (x))
701*e4b17023SJohn Marino     {
702*e4b17023SJohn Marino       if (reg_use_count == MAX_USES)
703*e4b17023SJohn Marino 	return;
704*e4b17023SJohn Marino 
705*e4b17023SJohn Marino       reg_use_table[reg_use_count] = x;
706*e4b17023SJohn Marino       reg_use_count++;
707*e4b17023SJohn Marino     }
708*e4b17023SJohn Marino 
709*e4b17023SJohn Marino   /* Recursively scan the operands of this expression.  */
710*e4b17023SJohn Marino 
711*e4b17023SJohn Marino   for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--)
712*e4b17023SJohn Marino     {
713*e4b17023SJohn Marino       if (fmt[i] == 'e')
714*e4b17023SJohn Marino 	{
715*e4b17023SJohn Marino 	  /* If we are about to do the last recursive call
716*e4b17023SJohn Marino 	     needed at this level, change it into iteration.
717*e4b17023SJohn Marino 	     This function is called enough to be worth it.  */
718*e4b17023SJohn Marino 	  if (i == 0)
719*e4b17023SJohn Marino 	    {
720*e4b17023SJohn Marino 	      x = XEXP (x, 0);
721*e4b17023SJohn Marino 	      goto repeat;
722*e4b17023SJohn Marino 	    }
723*e4b17023SJohn Marino 
724*e4b17023SJohn Marino 	  find_used_regs (&XEXP (x, i), data);
725*e4b17023SJohn Marino 	}
726*e4b17023SJohn Marino       else if (fmt[i] == 'E')
727*e4b17023SJohn Marino 	for (j = 0; j < XVECLEN (x, i); j++)
728*e4b17023SJohn Marino 	  find_used_regs (&XVECEXP (x, i, j), data);
729*e4b17023SJohn Marino     }
730*e4b17023SJohn Marino }
731*e4b17023SJohn Marino 
732*e4b17023SJohn Marino /* Try to replace all uses of FROM in INSN with TO.
733*e4b17023SJohn Marino    Return nonzero if successful.  */
734*e4b17023SJohn Marino 
735*e4b17023SJohn Marino static int
try_replace_reg(rtx from,rtx to,rtx insn)736*e4b17023SJohn Marino try_replace_reg (rtx from, rtx to, rtx insn)
737*e4b17023SJohn Marino {
738*e4b17023SJohn Marino   rtx note = find_reg_equal_equiv_note (insn);
739*e4b17023SJohn Marino   rtx src = 0;
740*e4b17023SJohn Marino   int success = 0;
741*e4b17023SJohn Marino   rtx set = single_set (insn);
742*e4b17023SJohn Marino 
743*e4b17023SJohn Marino   /* Usually we substitute easy stuff, so we won't copy everything.
744*e4b17023SJohn Marino      We however need to take care to not duplicate non-trivial CONST
745*e4b17023SJohn Marino      expressions.  */
746*e4b17023SJohn Marino   to = copy_rtx (to);
747*e4b17023SJohn Marino 
748*e4b17023SJohn Marino   validate_replace_src_group (from, to, insn);
749*e4b17023SJohn Marino   if (num_changes_pending () && apply_change_group ())
750*e4b17023SJohn Marino     success = 1;
751*e4b17023SJohn Marino 
752*e4b17023SJohn Marino   /* Try to simplify SET_SRC if we have substituted a constant.  */
753*e4b17023SJohn Marino   if (success && set && CONSTANT_P (to))
754*e4b17023SJohn Marino     {
755*e4b17023SJohn Marino       src = simplify_rtx (SET_SRC (set));
756*e4b17023SJohn Marino 
757*e4b17023SJohn Marino       if (src)
758*e4b17023SJohn Marino 	validate_change (insn, &SET_SRC (set), src, 0);
759*e4b17023SJohn Marino     }
760*e4b17023SJohn Marino 
761*e4b17023SJohn Marino   /* If there is already a REG_EQUAL note, update the expression in it
762*e4b17023SJohn Marino      with our replacement.  */
763*e4b17023SJohn Marino   if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL)
764*e4b17023SJohn Marino     set_unique_reg_note (insn, REG_EQUAL,
765*e4b17023SJohn Marino 			 simplify_replace_rtx (XEXP (note, 0), from, to));
766*e4b17023SJohn Marino   if (!success && set && reg_mentioned_p (from, SET_SRC (set)))
767*e4b17023SJohn Marino     {
768*e4b17023SJohn Marino       /* If above failed and this is a single set, try to simplify the source
769*e4b17023SJohn Marino 	 of the set given our substitution.  We could perhaps try this for
770*e4b17023SJohn Marino 	 multiple SETs, but it probably won't buy us anything.  */
771*e4b17023SJohn Marino       src = simplify_replace_rtx (SET_SRC (set), from, to);
772*e4b17023SJohn Marino 
773*e4b17023SJohn Marino       if (!rtx_equal_p (src, SET_SRC (set))
774*e4b17023SJohn Marino 	  && validate_change (insn, &SET_SRC (set), src, 0))
775*e4b17023SJohn Marino 	success = 1;
776*e4b17023SJohn Marino 
777*e4b17023SJohn Marino       /* If we've failed perform the replacement, have a single SET to
778*e4b17023SJohn Marino 	 a REG destination and don't yet have a note, add a REG_EQUAL note
779*e4b17023SJohn Marino 	 to not lose information.  */
780*e4b17023SJohn Marino       if (!success && note == 0 && set != 0 && REG_P (SET_DEST (set)))
781*e4b17023SJohn Marino 	note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src));
782*e4b17023SJohn Marino     }
783*e4b17023SJohn Marino 
784*e4b17023SJohn Marino   if (set && MEM_P (SET_DEST (set)) && reg_mentioned_p (from, SET_DEST (set)))
785*e4b17023SJohn Marino     {
786*e4b17023SJohn Marino       /* Registers can also appear as uses in SET_DEST if it is a MEM.
787*e4b17023SJohn Marino          We could perhaps try this for multiple SETs, but it probably
788*e4b17023SJohn Marino          won't buy us anything.  */
789*e4b17023SJohn Marino       rtx dest = simplify_replace_rtx (SET_DEST (set), from, to);
790*e4b17023SJohn Marino 
791*e4b17023SJohn Marino       if (!rtx_equal_p (dest, SET_DEST (set))
792*e4b17023SJohn Marino           && validate_change (insn, &SET_DEST (set), dest, 0))
793*e4b17023SJohn Marino         success = 1;
794*e4b17023SJohn Marino     }
795*e4b17023SJohn Marino 
796*e4b17023SJohn Marino   /* REG_EQUAL may get simplified into register.
797*e4b17023SJohn Marino      We don't allow that. Remove that note. This code ought
798*e4b17023SJohn Marino      not to happen, because previous code ought to synthesize
799*e4b17023SJohn Marino      reg-reg move, but be on the safe side.  */
800*e4b17023SJohn Marino   if (note && REG_NOTE_KIND (note) == REG_EQUAL && REG_P (XEXP (note, 0)))
801*e4b17023SJohn Marino     remove_note (insn, note);
802*e4b17023SJohn Marino 
803*e4b17023SJohn Marino   return success;
804*e4b17023SJohn Marino }
805*e4b17023SJohn Marino 
806*e4b17023SJohn Marino /* Find a set of REGNOs that are available on entry to INSN's block.  Return
807*e4b17023SJohn Marino    NULL no such set is found.  */
808*e4b17023SJohn Marino 
809*e4b17023SJohn Marino static struct expr *
find_avail_set(int regno,rtx insn)810*e4b17023SJohn Marino find_avail_set (int regno, rtx insn)
811*e4b17023SJohn Marino {
812*e4b17023SJohn Marino   /* SET1 contains the last set found that can be returned to the caller for
813*e4b17023SJohn Marino      use in a substitution.  */
814*e4b17023SJohn Marino   struct expr *set1 = 0;
815*e4b17023SJohn Marino 
816*e4b17023SJohn Marino   /* Loops are not possible here.  To get a loop we would need two sets
817*e4b17023SJohn Marino      available at the start of the block containing INSN.  i.e. we would
818*e4b17023SJohn Marino      need two sets like this available at the start of the block:
819*e4b17023SJohn Marino 
820*e4b17023SJohn Marino        (set (reg X) (reg Y))
821*e4b17023SJohn Marino        (set (reg Y) (reg X))
822*e4b17023SJohn Marino 
823*e4b17023SJohn Marino      This can not happen since the set of (reg Y) would have killed the
824*e4b17023SJohn Marino      set of (reg X) making it unavailable at the start of this block.  */
825*e4b17023SJohn Marino   while (1)
826*e4b17023SJohn Marino     {
827*e4b17023SJohn Marino       rtx src;
828*e4b17023SJohn Marino       struct expr *set = lookup_set (regno, &set_hash_table);
829*e4b17023SJohn Marino 
830*e4b17023SJohn Marino       /* Find a set that is available at the start of the block
831*e4b17023SJohn Marino 	 which contains INSN.  */
832*e4b17023SJohn Marino       while (set)
833*e4b17023SJohn Marino 	{
834*e4b17023SJohn Marino 	  if (TEST_BIT (cprop_avin[BLOCK_FOR_INSN (insn)->index],
835*e4b17023SJohn Marino 			set->bitmap_index))
836*e4b17023SJohn Marino 	    break;
837*e4b17023SJohn Marino 	  set = next_set (regno, set);
838*e4b17023SJohn Marino 	}
839*e4b17023SJohn Marino 
840*e4b17023SJohn Marino       /* If no available set was found we've reached the end of the
841*e4b17023SJohn Marino 	 (possibly empty) copy chain.  */
842*e4b17023SJohn Marino       if (set == 0)
843*e4b17023SJohn Marino 	break;
844*e4b17023SJohn Marino 
845*e4b17023SJohn Marino       src = set->src;
846*e4b17023SJohn Marino 
847*e4b17023SJohn Marino       /* We know the set is available.
848*e4b17023SJohn Marino 	 Now check that SRC is locally anticipatable (i.e. none of the
849*e4b17023SJohn Marino 	 source operands have changed since the start of the block).
850*e4b17023SJohn Marino 
851*e4b17023SJohn Marino          If the source operand changed, we may still use it for the next
852*e4b17023SJohn Marino          iteration of this loop, but we may not use it for substitutions.  */
853*e4b17023SJohn Marino 
854*e4b17023SJohn Marino       if (cprop_constant_p (src) || reg_not_set_p (src, insn))
855*e4b17023SJohn Marino 	set1 = set;
856*e4b17023SJohn Marino 
857*e4b17023SJohn Marino       /* If the source of the set is anything except a register, then
858*e4b17023SJohn Marino 	 we have reached the end of the copy chain.  */
859*e4b17023SJohn Marino       if (! REG_P (src))
860*e4b17023SJohn Marino 	break;
861*e4b17023SJohn Marino 
862*e4b17023SJohn Marino       /* Follow the copy chain, i.e. start another iteration of the loop
863*e4b17023SJohn Marino 	 and see if we have an available copy into SRC.  */
864*e4b17023SJohn Marino       regno = REGNO (src);
865*e4b17023SJohn Marino     }
866*e4b17023SJohn Marino 
867*e4b17023SJohn Marino   /* SET1 holds the last set that was available and anticipatable at
868*e4b17023SJohn Marino      INSN.  */
869*e4b17023SJohn Marino   return set1;
870*e4b17023SJohn Marino }
871*e4b17023SJohn Marino 
872*e4b17023SJohn Marino /* Subroutine of cprop_insn that tries to propagate constants into
873*e4b17023SJohn Marino    JUMP_INSNS.  JUMP must be a conditional jump.  If SETCC is non-NULL
874*e4b17023SJohn Marino    it is the instruction that immediately precedes JUMP, and must be a
875*e4b17023SJohn Marino    single SET of a register.  FROM is what we will try to replace,
876*e4b17023SJohn Marino    SRC is the constant we will try to substitute for it.  Return nonzero
877*e4b17023SJohn Marino    if a change was made.  */
878*e4b17023SJohn Marino 
879*e4b17023SJohn Marino static int
cprop_jump(basic_block bb,rtx setcc,rtx jump,rtx from,rtx src)880*e4b17023SJohn Marino cprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src)
881*e4b17023SJohn Marino {
882*e4b17023SJohn Marino   rtx new_rtx, set_src, note_src;
883*e4b17023SJohn Marino   rtx set = pc_set (jump);
884*e4b17023SJohn Marino   rtx note = find_reg_equal_equiv_note (jump);
885*e4b17023SJohn Marino 
886*e4b17023SJohn Marino   if (note)
887*e4b17023SJohn Marino     {
888*e4b17023SJohn Marino       note_src = XEXP (note, 0);
889*e4b17023SJohn Marino       if (GET_CODE (note_src) == EXPR_LIST)
890*e4b17023SJohn Marino 	note_src = NULL_RTX;
891*e4b17023SJohn Marino     }
892*e4b17023SJohn Marino   else note_src = NULL_RTX;
893*e4b17023SJohn Marino 
894*e4b17023SJohn Marino   /* Prefer REG_EQUAL notes except those containing EXPR_LISTs.  */
895*e4b17023SJohn Marino   set_src = note_src ? note_src : SET_SRC (set);
896*e4b17023SJohn Marino 
897*e4b17023SJohn Marino   /* First substitute the SETCC condition into the JUMP instruction,
898*e4b17023SJohn Marino      then substitute that given values into this expanded JUMP.  */
899*e4b17023SJohn Marino   if (setcc != NULL_RTX
900*e4b17023SJohn Marino       && !modified_between_p (from, setcc, jump)
901*e4b17023SJohn Marino       && !modified_between_p (src, setcc, jump))
902*e4b17023SJohn Marino     {
903*e4b17023SJohn Marino       rtx setcc_src;
904*e4b17023SJohn Marino       rtx setcc_set = single_set (setcc);
905*e4b17023SJohn Marino       rtx setcc_note = find_reg_equal_equiv_note (setcc);
906*e4b17023SJohn Marino       setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST)
907*e4b17023SJohn Marino 		? XEXP (setcc_note, 0) : SET_SRC (setcc_set);
908*e4b17023SJohn Marino       set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set),
909*e4b17023SJohn Marino 				      setcc_src);
910*e4b17023SJohn Marino     }
911*e4b17023SJohn Marino   else
912*e4b17023SJohn Marino     setcc = NULL_RTX;
913*e4b17023SJohn Marino 
914*e4b17023SJohn Marino   new_rtx = simplify_replace_rtx (set_src, from, src);
915*e4b17023SJohn Marino 
916*e4b17023SJohn Marino   /* If no simplification can be made, then try the next register.  */
917*e4b17023SJohn Marino   if (rtx_equal_p (new_rtx, SET_SRC (set)))
918*e4b17023SJohn Marino     return 0;
919*e4b17023SJohn Marino 
920*e4b17023SJohn Marino   /* If this is now a no-op delete it, otherwise this must be a valid insn.  */
921*e4b17023SJohn Marino   if (new_rtx == pc_rtx)
922*e4b17023SJohn Marino     delete_insn (jump);
923*e4b17023SJohn Marino   else
924*e4b17023SJohn Marino     {
925*e4b17023SJohn Marino       /* Ensure the value computed inside the jump insn to be equivalent
926*e4b17023SJohn Marino          to one computed by setcc.  */
927*e4b17023SJohn Marino       if (setcc && modified_in_p (new_rtx, setcc))
928*e4b17023SJohn Marino 	return 0;
929*e4b17023SJohn Marino       if (! validate_unshare_change (jump, &SET_SRC (set), new_rtx, 0))
930*e4b17023SJohn Marino 	{
931*e4b17023SJohn Marino 	  /* When (some) constants are not valid in a comparison, and there
932*e4b17023SJohn Marino 	     are two registers to be replaced by constants before the entire
933*e4b17023SJohn Marino 	     comparison can be folded into a constant, we need to keep
934*e4b17023SJohn Marino 	     intermediate information in REG_EQUAL notes.  For targets with
935*e4b17023SJohn Marino 	     separate compare insns, such notes are added by try_replace_reg.
936*e4b17023SJohn Marino 	     When we have a combined compare-and-branch instruction, however,
937*e4b17023SJohn Marino 	     we need to attach a note to the branch itself to make this
938*e4b17023SJohn Marino 	     optimization work.  */
939*e4b17023SJohn Marino 
940*e4b17023SJohn Marino 	  if (!rtx_equal_p (new_rtx, note_src))
941*e4b17023SJohn Marino 	    set_unique_reg_note (jump, REG_EQUAL, copy_rtx (new_rtx));
942*e4b17023SJohn Marino 	  return 0;
943*e4b17023SJohn Marino 	}
944*e4b17023SJohn Marino 
945*e4b17023SJohn Marino       /* Remove REG_EQUAL note after simplification.  */
946*e4b17023SJohn Marino       if (note_src)
947*e4b17023SJohn Marino 	remove_note (jump, note);
948*e4b17023SJohn Marino      }
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino #ifdef HAVE_cc0
951*e4b17023SJohn Marino   /* Delete the cc0 setter.  */
952*e4b17023SJohn Marino   if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc))))
953*e4b17023SJohn Marino     delete_insn (setcc);
954*e4b17023SJohn Marino #endif
955*e4b17023SJohn Marino 
956*e4b17023SJohn Marino   global_const_prop_count++;
957*e4b17023SJohn Marino   if (dump_file != NULL)
958*e4b17023SJohn Marino     {
959*e4b17023SJohn Marino       fprintf (dump_file,
960*e4b17023SJohn Marino 	       "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with"
961*e4b17023SJohn Marino 	       "constant ", REGNO (from), INSN_UID (jump));
962*e4b17023SJohn Marino       print_rtl (dump_file, src);
963*e4b17023SJohn Marino       fprintf (dump_file, "\n");
964*e4b17023SJohn Marino     }
965*e4b17023SJohn Marino   purge_dead_edges (bb);
966*e4b17023SJohn Marino 
967*e4b17023SJohn Marino   /* If a conditional jump has been changed into unconditional jump, remove
968*e4b17023SJohn Marino      the jump and make the edge fallthru - this is always called in
969*e4b17023SJohn Marino      cfglayout mode.  */
970*e4b17023SJohn Marino   if (new_rtx != pc_rtx && simplejump_p (jump))
971*e4b17023SJohn Marino     {
972*e4b17023SJohn Marino       edge e;
973*e4b17023SJohn Marino       edge_iterator ei;
974*e4b17023SJohn Marino 
975*e4b17023SJohn Marino       FOR_EACH_EDGE (e, ei, bb->succs)
976*e4b17023SJohn Marino 	if (e->dest != EXIT_BLOCK_PTR
977*e4b17023SJohn Marino 	    && BB_HEAD (e->dest) == JUMP_LABEL (jump))
978*e4b17023SJohn Marino 	  {
979*e4b17023SJohn Marino 	    e->flags |= EDGE_FALLTHRU;
980*e4b17023SJohn Marino 	    break;
981*e4b17023SJohn Marino 	  }
982*e4b17023SJohn Marino       delete_insn (jump);
983*e4b17023SJohn Marino     }
984*e4b17023SJohn Marino 
985*e4b17023SJohn Marino   return 1;
986*e4b17023SJohn Marino }
987*e4b17023SJohn Marino 
988*e4b17023SJohn Marino /* Subroutine of cprop_insn that tries to propagate constants.  FROM is what
989*e4b17023SJohn Marino    we will try to replace, SRC is the constant we will try to substitute for
990*e4b17023SJohn Marino    it and INSN is the instruction where this will be happening.  */
991*e4b17023SJohn Marino 
992*e4b17023SJohn Marino static int
constprop_register(rtx from,rtx src,rtx insn)993*e4b17023SJohn Marino constprop_register (rtx from, rtx src, rtx insn)
994*e4b17023SJohn Marino {
995*e4b17023SJohn Marino   rtx sset;
996*e4b17023SJohn Marino 
997*e4b17023SJohn Marino   /* Check for reg or cc0 setting instructions followed by
998*e4b17023SJohn Marino      conditional branch instructions first.  */
999*e4b17023SJohn Marino   if ((sset = single_set (insn)) != NULL
1000*e4b17023SJohn Marino       && NEXT_INSN (insn)
1001*e4b17023SJohn Marino       && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn)))
1002*e4b17023SJohn Marino     {
1003*e4b17023SJohn Marino       rtx dest = SET_DEST (sset);
1004*e4b17023SJohn Marino       if ((REG_P (dest) || CC0_P (dest))
1005*e4b17023SJohn Marino 	  && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn),
1006*e4b17023SJohn Marino 			 from, src))
1007*e4b17023SJohn Marino 	return 1;
1008*e4b17023SJohn Marino     }
1009*e4b17023SJohn Marino 
1010*e4b17023SJohn Marino   /* Handle normal insns next.  */
1011*e4b17023SJohn Marino   if (NONJUMP_INSN_P (insn) && try_replace_reg (from, src, insn))
1012*e4b17023SJohn Marino     return 1;
1013*e4b17023SJohn Marino 
1014*e4b17023SJohn Marino   /* Try to propagate a CONST_INT into a conditional jump.
1015*e4b17023SJohn Marino      We're pretty specific about what we will handle in this
1016*e4b17023SJohn Marino      code, we can extend this as necessary over time.
1017*e4b17023SJohn Marino 
1018*e4b17023SJohn Marino      Right now the insn in question must look like
1019*e4b17023SJohn Marino      (set (pc) (if_then_else ...))  */
1020*e4b17023SJohn Marino   else if (any_condjump_p (insn) && onlyjump_p (insn))
1021*e4b17023SJohn Marino     return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, src);
1022*e4b17023SJohn Marino   return 0;
1023*e4b17023SJohn Marino }
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino /* Perform constant and copy propagation on INSN.
1026*e4b17023SJohn Marino    Return nonzero if a change was made.  */
1027*e4b17023SJohn Marino 
1028*e4b17023SJohn Marino static int
cprop_insn(rtx insn)1029*e4b17023SJohn Marino cprop_insn (rtx insn)
1030*e4b17023SJohn Marino {
1031*e4b17023SJohn Marino   unsigned i;
1032*e4b17023SJohn Marino   int changed = 0, changed_this_round;
1033*e4b17023SJohn Marino   rtx note;
1034*e4b17023SJohn Marino 
1035*e4b17023SJohn Marino retry:
1036*e4b17023SJohn Marino   changed_this_round = 0;
1037*e4b17023SJohn Marino   reg_use_count = 0;
1038*e4b17023SJohn Marino   note_uses (&PATTERN (insn), find_used_regs, NULL);
1039*e4b17023SJohn Marino 
1040*e4b17023SJohn Marino   /* We may win even when propagating constants into notes.  */
1041*e4b17023SJohn Marino   note = find_reg_equal_equiv_note (insn);
1042*e4b17023SJohn Marino   if (note)
1043*e4b17023SJohn Marino     find_used_regs (&XEXP (note, 0), NULL);
1044*e4b17023SJohn Marino 
1045*e4b17023SJohn Marino   for (i = 0; i < reg_use_count; i++)
1046*e4b17023SJohn Marino     {
1047*e4b17023SJohn Marino       rtx reg_used = reg_use_table[i];
1048*e4b17023SJohn Marino       unsigned int regno = REGNO (reg_used);
1049*e4b17023SJohn Marino       rtx src;
1050*e4b17023SJohn Marino       struct expr *set;
1051*e4b17023SJohn Marino 
1052*e4b17023SJohn Marino       /* If the register has already been set in this block, there's
1053*e4b17023SJohn Marino 	 nothing we can do.  */
1054*e4b17023SJohn Marino       if (! reg_not_set_p (reg_used, insn))
1055*e4b17023SJohn Marino 	continue;
1056*e4b17023SJohn Marino 
1057*e4b17023SJohn Marino       /* Find an assignment that sets reg_used and is available
1058*e4b17023SJohn Marino 	 at the start of the block.  */
1059*e4b17023SJohn Marino       set = find_avail_set (regno, insn);
1060*e4b17023SJohn Marino       if (! set)
1061*e4b17023SJohn Marino 	continue;
1062*e4b17023SJohn Marino 
1063*e4b17023SJohn Marino       src = set->src;
1064*e4b17023SJohn Marino 
1065*e4b17023SJohn Marino       /* Constant propagation.  */
1066*e4b17023SJohn Marino       if (cprop_constant_p (src))
1067*e4b17023SJohn Marino 	{
1068*e4b17023SJohn Marino           if (constprop_register (reg_used, src, insn))
1069*e4b17023SJohn Marino 	    {
1070*e4b17023SJohn Marino 	      changed_this_round = changed = 1;
1071*e4b17023SJohn Marino 	      global_const_prop_count++;
1072*e4b17023SJohn Marino 	      if (dump_file != NULL)
1073*e4b17023SJohn Marino 		{
1074*e4b17023SJohn Marino 		  fprintf (dump_file,
1075*e4b17023SJohn Marino 			   "GLOBAL CONST-PROP: Replacing reg %d in ", regno);
1076*e4b17023SJohn Marino 		  fprintf (dump_file, "insn %d with constant ",
1077*e4b17023SJohn Marino 			   INSN_UID (insn));
1078*e4b17023SJohn Marino 		  print_rtl (dump_file, src);
1079*e4b17023SJohn Marino 		  fprintf (dump_file, "\n");
1080*e4b17023SJohn Marino 		}
1081*e4b17023SJohn Marino 	      if (INSN_DELETED_P (insn))
1082*e4b17023SJohn Marino 		return 1;
1083*e4b17023SJohn Marino 	    }
1084*e4b17023SJohn Marino 	}
1085*e4b17023SJohn Marino       else if (REG_P (src)
1086*e4b17023SJohn Marino 	       && REGNO (src) >= FIRST_PSEUDO_REGISTER
1087*e4b17023SJohn Marino 	       && REGNO (src) != regno)
1088*e4b17023SJohn Marino 	{
1089*e4b17023SJohn Marino 	  if (try_replace_reg (reg_used, src, insn))
1090*e4b17023SJohn Marino 	    {
1091*e4b17023SJohn Marino 	      changed_this_round = changed = 1;
1092*e4b17023SJohn Marino 	      global_copy_prop_count++;
1093*e4b17023SJohn Marino 	      if (dump_file != NULL)
1094*e4b17023SJohn Marino 		{
1095*e4b17023SJohn Marino 		  fprintf (dump_file,
1096*e4b17023SJohn Marino 			   "GLOBAL COPY-PROP: Replacing reg %d in insn %d",
1097*e4b17023SJohn Marino 			   regno, INSN_UID (insn));
1098*e4b17023SJohn Marino 		  fprintf (dump_file, " with reg %d\n", REGNO (src));
1099*e4b17023SJohn Marino 		}
1100*e4b17023SJohn Marino 
1101*e4b17023SJohn Marino 	      /* The original insn setting reg_used may or may not now be
1102*e4b17023SJohn Marino 		 deletable.  We leave the deletion to DCE.  */
1103*e4b17023SJohn Marino 	      /* FIXME: If it turns out that the insn isn't deletable,
1104*e4b17023SJohn Marino 		 then we may have unnecessarily extended register lifetimes
1105*e4b17023SJohn Marino 		 and made things worse.  */
1106*e4b17023SJohn Marino 	    }
1107*e4b17023SJohn Marino 	}
1108*e4b17023SJohn Marino 
1109*e4b17023SJohn Marino       /* If try_replace_reg simplified the insn, the regs found
1110*e4b17023SJohn Marino 	 by find_used_regs may not be valid anymore.  Start over.  */
1111*e4b17023SJohn Marino       if (changed_this_round)
1112*e4b17023SJohn Marino 	goto retry;
1113*e4b17023SJohn Marino     }
1114*e4b17023SJohn Marino 
1115*e4b17023SJohn Marino   if (changed && DEBUG_INSN_P (insn))
1116*e4b17023SJohn Marino     return 0;
1117*e4b17023SJohn Marino 
1118*e4b17023SJohn Marino   return changed;
1119*e4b17023SJohn Marino }
1120*e4b17023SJohn Marino 
1121*e4b17023SJohn Marino /* Like find_used_regs, but avoid recording uses that appear in
1122*e4b17023SJohn Marino    input-output contexts such as zero_extract or pre_dec.  This
1123*e4b17023SJohn Marino    restricts the cases we consider to those for which local cprop
1124*e4b17023SJohn Marino    can legitimately make replacements.  */
1125*e4b17023SJohn Marino 
1126*e4b17023SJohn Marino static void
local_cprop_find_used_regs(rtx * xptr,void * data)1127*e4b17023SJohn Marino local_cprop_find_used_regs (rtx *xptr, void *data)
1128*e4b17023SJohn Marino {
1129*e4b17023SJohn Marino   rtx x = *xptr;
1130*e4b17023SJohn Marino 
1131*e4b17023SJohn Marino   if (x == 0)
1132*e4b17023SJohn Marino     return;
1133*e4b17023SJohn Marino 
1134*e4b17023SJohn Marino   switch (GET_CODE (x))
1135*e4b17023SJohn Marino     {
1136*e4b17023SJohn Marino     case ZERO_EXTRACT:
1137*e4b17023SJohn Marino     case SIGN_EXTRACT:
1138*e4b17023SJohn Marino     case STRICT_LOW_PART:
1139*e4b17023SJohn Marino       return;
1140*e4b17023SJohn Marino 
1141*e4b17023SJohn Marino     case PRE_DEC:
1142*e4b17023SJohn Marino     case PRE_INC:
1143*e4b17023SJohn Marino     case POST_DEC:
1144*e4b17023SJohn Marino     case POST_INC:
1145*e4b17023SJohn Marino     case PRE_MODIFY:
1146*e4b17023SJohn Marino     case POST_MODIFY:
1147*e4b17023SJohn Marino       /* Can only legitimately appear this early in the context of
1148*e4b17023SJohn Marino 	 stack pushes for function arguments, but handle all of the
1149*e4b17023SJohn Marino 	 codes nonetheless.  */
1150*e4b17023SJohn Marino       return;
1151*e4b17023SJohn Marino 
1152*e4b17023SJohn Marino     case SUBREG:
1153*e4b17023SJohn Marino       /* Setting a subreg of a register larger than word_mode leaves
1154*e4b17023SJohn Marino 	 the non-written words unchanged.  */
1155*e4b17023SJohn Marino       if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) > BITS_PER_WORD)
1156*e4b17023SJohn Marino 	return;
1157*e4b17023SJohn Marino       break;
1158*e4b17023SJohn Marino 
1159*e4b17023SJohn Marino     default:
1160*e4b17023SJohn Marino       break;
1161*e4b17023SJohn Marino     }
1162*e4b17023SJohn Marino 
1163*e4b17023SJohn Marino   find_used_regs (xptr, data);
1164*e4b17023SJohn Marino }
1165*e4b17023SJohn Marino 
1166*e4b17023SJohn Marino /* Try to perform local const/copy propagation on X in INSN.  */
1167*e4b17023SJohn Marino 
1168*e4b17023SJohn Marino static bool
do_local_cprop(rtx x,rtx insn)1169*e4b17023SJohn Marino do_local_cprop (rtx x, rtx insn)
1170*e4b17023SJohn Marino {
1171*e4b17023SJohn Marino   rtx newreg = NULL, newcnst = NULL;
1172*e4b17023SJohn Marino 
1173*e4b17023SJohn Marino   /* Rule out USE instructions and ASM statements as we don't want to
1174*e4b17023SJohn Marino      change the hard registers mentioned.  */
1175*e4b17023SJohn Marino   if (REG_P (x)
1176*e4b17023SJohn Marino       && (REGNO (x) >= FIRST_PSEUDO_REGISTER
1177*e4b17023SJohn Marino           || (GET_CODE (PATTERN (insn)) != USE
1178*e4b17023SJohn Marino 	      && asm_noperands (PATTERN (insn)) < 0)))
1179*e4b17023SJohn Marino     {
1180*e4b17023SJohn Marino       cselib_val *val = cselib_lookup (x, GET_MODE (x), 0, VOIDmode);
1181*e4b17023SJohn Marino       struct elt_loc_list *l;
1182*e4b17023SJohn Marino 
1183*e4b17023SJohn Marino       if (!val)
1184*e4b17023SJohn Marino 	return false;
1185*e4b17023SJohn Marino       for (l = val->locs; l; l = l->next)
1186*e4b17023SJohn Marino 	{
1187*e4b17023SJohn Marino 	  rtx this_rtx = l->loc;
1188*e4b17023SJohn Marino 	  rtx note;
1189*e4b17023SJohn Marino 
1190*e4b17023SJohn Marino 	  if (cprop_constant_p (this_rtx))
1191*e4b17023SJohn Marino 	    newcnst = this_rtx;
1192*e4b17023SJohn Marino 	  if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER
1193*e4b17023SJohn Marino 	      /* Don't copy propagate if it has attached REG_EQUIV note.
1194*e4b17023SJohn Marino 		 At this point this only function parameters should have
1195*e4b17023SJohn Marino 		 REG_EQUIV notes and if the argument slot is used somewhere
1196*e4b17023SJohn Marino 		 explicitly, it means address of parameter has been taken,
1197*e4b17023SJohn Marino 		 so we should not extend the lifetime of the pseudo.  */
1198*e4b17023SJohn Marino 	      && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX))
1199*e4b17023SJohn Marino 		  || ! MEM_P (XEXP (note, 0))))
1200*e4b17023SJohn Marino 	    newreg = this_rtx;
1201*e4b17023SJohn Marino 	}
1202*e4b17023SJohn Marino       if (newcnst && constprop_register (x, newcnst, insn))
1203*e4b17023SJohn Marino 	{
1204*e4b17023SJohn Marino 	  if (dump_file != NULL)
1205*e4b17023SJohn Marino 	    {
1206*e4b17023SJohn Marino 	      fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ",
1207*e4b17023SJohn Marino 		       REGNO (x));
1208*e4b17023SJohn Marino 	      fprintf (dump_file, "insn %d with constant ",
1209*e4b17023SJohn Marino 		       INSN_UID (insn));
1210*e4b17023SJohn Marino 	      print_rtl (dump_file, newcnst);
1211*e4b17023SJohn Marino 	      fprintf (dump_file, "\n");
1212*e4b17023SJohn Marino 	    }
1213*e4b17023SJohn Marino 	  local_const_prop_count++;
1214*e4b17023SJohn Marino 	  return true;
1215*e4b17023SJohn Marino 	}
1216*e4b17023SJohn Marino       else if (newreg && newreg != x && try_replace_reg (x, newreg, insn))
1217*e4b17023SJohn Marino 	{
1218*e4b17023SJohn Marino 	  if (dump_file != NULL)
1219*e4b17023SJohn Marino 	    {
1220*e4b17023SJohn Marino 	      fprintf (dump_file,
1221*e4b17023SJohn Marino 		       "LOCAL COPY-PROP: Replacing reg %d in insn %d",
1222*e4b17023SJohn Marino 		       REGNO (x), INSN_UID (insn));
1223*e4b17023SJohn Marino 	      fprintf (dump_file, " with reg %d\n", REGNO (newreg));
1224*e4b17023SJohn Marino 	    }
1225*e4b17023SJohn Marino 	  local_copy_prop_count++;
1226*e4b17023SJohn Marino 	  return true;
1227*e4b17023SJohn Marino 	}
1228*e4b17023SJohn Marino     }
1229*e4b17023SJohn Marino   return false;
1230*e4b17023SJohn Marino }
1231*e4b17023SJohn Marino 
1232*e4b17023SJohn Marino /* Do local const/copy propagation (i.e. within each basic block).  */
1233*e4b17023SJohn Marino 
1234*e4b17023SJohn Marino static int
local_cprop_pass(void)1235*e4b17023SJohn Marino local_cprop_pass (void)
1236*e4b17023SJohn Marino {
1237*e4b17023SJohn Marino   basic_block bb;
1238*e4b17023SJohn Marino   rtx insn;
1239*e4b17023SJohn Marino   bool changed = false;
1240*e4b17023SJohn Marino   unsigned i;
1241*e4b17023SJohn Marino 
1242*e4b17023SJohn Marino   cselib_init (0);
1243*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1244*e4b17023SJohn Marino     {
1245*e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
1246*e4b17023SJohn Marino 	{
1247*e4b17023SJohn Marino 	  if (INSN_P (insn))
1248*e4b17023SJohn Marino 	    {
1249*e4b17023SJohn Marino 	      rtx note = find_reg_equal_equiv_note (insn);
1250*e4b17023SJohn Marino 	      do
1251*e4b17023SJohn Marino 		{
1252*e4b17023SJohn Marino 		  reg_use_count = 0;
1253*e4b17023SJohn Marino 		  note_uses (&PATTERN (insn), local_cprop_find_used_regs,
1254*e4b17023SJohn Marino 			     NULL);
1255*e4b17023SJohn Marino 		  if (note)
1256*e4b17023SJohn Marino 		    local_cprop_find_used_regs (&XEXP (note, 0), NULL);
1257*e4b17023SJohn Marino 
1258*e4b17023SJohn Marino 		  for (i = 0; i < reg_use_count; i++)
1259*e4b17023SJohn Marino 		    {
1260*e4b17023SJohn Marino 		      if (do_local_cprop (reg_use_table[i], insn))
1261*e4b17023SJohn Marino 			{
1262*e4b17023SJohn Marino 			  if (!DEBUG_INSN_P (insn))
1263*e4b17023SJohn Marino 			    changed = true;
1264*e4b17023SJohn Marino 			  break;
1265*e4b17023SJohn Marino 			}
1266*e4b17023SJohn Marino 		    }
1267*e4b17023SJohn Marino 		  if (INSN_DELETED_P (insn))
1268*e4b17023SJohn Marino 		    break;
1269*e4b17023SJohn Marino 		}
1270*e4b17023SJohn Marino 	      while (i < reg_use_count);
1271*e4b17023SJohn Marino 	    }
1272*e4b17023SJohn Marino 	  cselib_process_insn (insn);
1273*e4b17023SJohn Marino 	}
1274*e4b17023SJohn Marino 
1275*e4b17023SJohn Marino       /* Forget everything at the end of a basic block.  */
1276*e4b17023SJohn Marino       cselib_clear_table ();
1277*e4b17023SJohn Marino     }
1278*e4b17023SJohn Marino 
1279*e4b17023SJohn Marino   cselib_finish ();
1280*e4b17023SJohn Marino 
1281*e4b17023SJohn Marino   return changed;
1282*e4b17023SJohn Marino }
1283*e4b17023SJohn Marino 
1284*e4b17023SJohn Marino /* Similar to get_condition, only the resulting condition must be
1285*e4b17023SJohn Marino    valid at JUMP, instead of at EARLIEST.
1286*e4b17023SJohn Marino 
1287*e4b17023SJohn Marino    This differs from noce_get_condition in ifcvt.c in that we prefer not to
1288*e4b17023SJohn Marino    settle for the condition variable in the jump instruction being integral.
1289*e4b17023SJohn Marino    We prefer to be able to record the value of a user variable, rather than
1290*e4b17023SJohn Marino    the value of a temporary used in a condition.  This could be solved by
1291*e4b17023SJohn Marino    recording the value of *every* register scanned by canonicalize_condition,
1292*e4b17023SJohn Marino    but this would require some code reorganization.  */
1293*e4b17023SJohn Marino 
1294*e4b17023SJohn Marino rtx
fis_get_condition(rtx jump)1295*e4b17023SJohn Marino fis_get_condition (rtx jump)
1296*e4b17023SJohn Marino {
1297*e4b17023SJohn Marino   return get_condition (jump, NULL, false, true);
1298*e4b17023SJohn Marino }
1299*e4b17023SJohn Marino 
1300*e4b17023SJohn Marino /* Check the comparison COND to see if we can safely form an implicit
1301*e4b17023SJohn Marino    set from it.  */
1302*e4b17023SJohn Marino 
1303*e4b17023SJohn Marino static bool
implicit_set_cond_p(const_rtx cond)1304*e4b17023SJohn Marino implicit_set_cond_p (const_rtx cond)
1305*e4b17023SJohn Marino {
1306*e4b17023SJohn Marino   enum machine_mode mode;
1307*e4b17023SJohn Marino   rtx cst;
1308*e4b17023SJohn Marino 
1309*e4b17023SJohn Marino   /* COND must be either an EQ or NE comparison.  */
1310*e4b17023SJohn Marino   if (GET_CODE (cond) != EQ && GET_CODE (cond) != NE)
1311*e4b17023SJohn Marino     return false;
1312*e4b17023SJohn Marino 
1313*e4b17023SJohn Marino   /* The first operand of COND must be a pseudo-reg.  */
1314*e4b17023SJohn Marino   if (! REG_P (XEXP (cond, 0))
1315*e4b17023SJohn Marino       || HARD_REGISTER_P (XEXP (cond, 0)))
1316*e4b17023SJohn Marino     return false;
1317*e4b17023SJohn Marino 
1318*e4b17023SJohn Marino   /* The second operand of COND must be a suitable constant.  */
1319*e4b17023SJohn Marino   mode = GET_MODE (XEXP (cond, 0));
1320*e4b17023SJohn Marino   cst = XEXP (cond, 1);
1321*e4b17023SJohn Marino 
1322*e4b17023SJohn Marino   /* We can't perform this optimization if either operand might be or might
1323*e4b17023SJohn Marino      contain a signed zero.  */
1324*e4b17023SJohn Marino   if (HONOR_SIGNED_ZEROS (mode))
1325*e4b17023SJohn Marino     {
1326*e4b17023SJohn Marino       /* It is sufficient to check if CST is or contains a zero.  We must
1327*e4b17023SJohn Marino 	 handle float, complex, and vector.  If any subpart is a zero, then
1328*e4b17023SJohn Marino 	 the optimization can't be performed.  */
1329*e4b17023SJohn Marino       /* ??? The complex and vector checks are not implemented yet.  We just
1330*e4b17023SJohn Marino 	 always return zero for them.  */
1331*e4b17023SJohn Marino       if (GET_CODE (cst) == CONST_DOUBLE)
1332*e4b17023SJohn Marino 	{
1333*e4b17023SJohn Marino 	  REAL_VALUE_TYPE d;
1334*e4b17023SJohn Marino 	  REAL_VALUE_FROM_CONST_DOUBLE (d, cst);
1335*e4b17023SJohn Marino 	  if (REAL_VALUES_EQUAL (d, dconst0))
1336*e4b17023SJohn Marino 	    return 0;
1337*e4b17023SJohn Marino 	}
1338*e4b17023SJohn Marino       else
1339*e4b17023SJohn Marino 	return 0;
1340*e4b17023SJohn Marino     }
1341*e4b17023SJohn Marino 
1342*e4b17023SJohn Marino   return cprop_constant_p (cst);
1343*e4b17023SJohn Marino }
1344*e4b17023SJohn Marino 
1345*e4b17023SJohn Marino /* Find the implicit sets of a function.  An "implicit set" is a constraint
1346*e4b17023SJohn Marino    on the value of a variable, implied by a conditional jump.  For example,
1347*e4b17023SJohn Marino    following "if (x == 2)", the then branch may be optimized as though the
1348*e4b17023SJohn Marino    conditional performed an "explicit set", in this example, "x = 2".  This
1349*e4b17023SJohn Marino    function records the set patterns that are implicit at the start of each
1350*e4b17023SJohn Marino    basic block.
1351*e4b17023SJohn Marino 
1352*e4b17023SJohn Marino    If an implicit set is found but the set is implicit on a critical edge,
1353*e4b17023SJohn Marino    this critical edge is split.
1354*e4b17023SJohn Marino 
1355*e4b17023SJohn Marino    Return true if the CFG was modified, false otherwise.  */
1356*e4b17023SJohn Marino 
1357*e4b17023SJohn Marino static bool
find_implicit_sets(void)1358*e4b17023SJohn Marino find_implicit_sets (void)
1359*e4b17023SJohn Marino {
1360*e4b17023SJohn Marino   basic_block bb, dest;
1361*e4b17023SJohn Marino   rtx cond, new_rtx;
1362*e4b17023SJohn Marino   unsigned int count = 0;
1363*e4b17023SJohn Marino   bool edges_split = false;
1364*e4b17023SJohn Marino   size_t implicit_sets_size = last_basic_block + 10;
1365*e4b17023SJohn Marino 
1366*e4b17023SJohn Marino   implicit_sets = XCNEWVEC (rtx, implicit_sets_size);
1367*e4b17023SJohn Marino 
1368*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1369*e4b17023SJohn Marino     {
1370*e4b17023SJohn Marino       /* Check for more than one successor.  */
1371*e4b17023SJohn Marino       if (EDGE_COUNT (bb->succs) <= 1)
1372*e4b17023SJohn Marino 	continue;
1373*e4b17023SJohn Marino 
1374*e4b17023SJohn Marino       cond = fis_get_condition (BB_END (bb));
1375*e4b17023SJohn Marino 
1376*e4b17023SJohn Marino       /* If no condition is found or if it isn't of a suitable form,
1377*e4b17023SJohn Marino 	 ignore it.  */
1378*e4b17023SJohn Marino       if (! cond || ! implicit_set_cond_p (cond))
1379*e4b17023SJohn Marino 	continue;
1380*e4b17023SJohn Marino 
1381*e4b17023SJohn Marino       dest = GET_CODE (cond) == EQ
1382*e4b17023SJohn Marino 	? BRANCH_EDGE (bb)->dest : FALLTHRU_EDGE (bb)->dest;
1383*e4b17023SJohn Marino 
1384*e4b17023SJohn Marino       /* If DEST doesn't go anywhere, ignore it.  */
1385*e4b17023SJohn Marino       if (! dest || dest == EXIT_BLOCK_PTR)
1386*e4b17023SJohn Marino 	continue;
1387*e4b17023SJohn Marino 
1388*e4b17023SJohn Marino       /* We have found a suitable implicit set.  Try to record it now as
1389*e4b17023SJohn Marino 	 a SET in DEST.  If DEST has more than one predecessor, the edge
1390*e4b17023SJohn Marino 	 between BB and DEST is a critical edge and we must split it,
1391*e4b17023SJohn Marino 	 because we can only record one implicit set per DEST basic block.  */
1392*e4b17023SJohn Marino       if (! single_pred_p (dest))
1393*e4b17023SJohn Marino         {
1394*e4b17023SJohn Marino 	  dest = split_edge (find_edge (bb, dest));
1395*e4b17023SJohn Marino 	  edges_split = true;
1396*e4b17023SJohn Marino 	}
1397*e4b17023SJohn Marino 
1398*e4b17023SJohn Marino       if (implicit_sets_size <= (size_t) dest->index)
1399*e4b17023SJohn Marino       {
1400*e4b17023SJohn Marino         size_t old_implicit_sets_size = implicit_sets_size;
1401*e4b17023SJohn Marino 	implicit_sets_size *= 2;
1402*e4b17023SJohn Marino 	implicit_sets = XRESIZEVEC (rtx, implicit_sets, implicit_sets_size);
1403*e4b17023SJohn Marino 	memset (implicit_sets + old_implicit_sets_size, 0,
1404*e4b17023SJohn Marino 		(implicit_sets_size - old_implicit_sets_size) * sizeof (rtx));
1405*e4b17023SJohn Marino       }
1406*e4b17023SJohn Marino 
1407*e4b17023SJohn Marino       new_rtx = gen_rtx_SET (VOIDmode, XEXP (cond, 0),
1408*e4b17023SJohn Marino 			     XEXP (cond, 1));
1409*e4b17023SJohn Marino       implicit_sets[dest->index] = new_rtx;
1410*e4b17023SJohn Marino       if (dump_file)
1411*e4b17023SJohn Marino 	{
1412*e4b17023SJohn Marino 	  fprintf(dump_file, "Implicit set of reg %d in ",
1413*e4b17023SJohn Marino 		  REGNO (XEXP (cond, 0)));
1414*e4b17023SJohn Marino 	  fprintf(dump_file, "basic block %d\n", dest->index);
1415*e4b17023SJohn Marino 	}
1416*e4b17023SJohn Marino       count++;
1417*e4b17023SJohn Marino     }
1418*e4b17023SJohn Marino 
1419*e4b17023SJohn Marino   if (dump_file)
1420*e4b17023SJohn Marino     fprintf (dump_file, "Found %d implicit sets\n", count);
1421*e4b17023SJohn Marino 
1422*e4b17023SJohn Marino   /* Confess our sins.  */
1423*e4b17023SJohn Marino   return edges_split;
1424*e4b17023SJohn Marino }
1425*e4b17023SJohn Marino 
1426*e4b17023SJohn Marino /* Bypass conditional jumps.  */
1427*e4b17023SJohn Marino 
1428*e4b17023SJohn Marino /* The value of last_basic_block at the beginning of the jump_bypass
1429*e4b17023SJohn Marino    pass.  The use of redirect_edge_and_branch_force may introduce new
1430*e4b17023SJohn Marino    basic blocks, but the data flow analysis is only valid for basic
1431*e4b17023SJohn Marino    block indices less than bypass_last_basic_block.  */
1432*e4b17023SJohn Marino 
1433*e4b17023SJohn Marino static int bypass_last_basic_block;
1434*e4b17023SJohn Marino 
1435*e4b17023SJohn Marino /* Find a set of REGNO to a constant that is available at the end of basic
1436*e4b17023SJohn Marino    block BB.  Return NULL if no such set is found.  Based heavily upon
1437*e4b17023SJohn Marino    find_avail_set.  */
1438*e4b17023SJohn Marino 
1439*e4b17023SJohn Marino static struct expr *
find_bypass_set(int regno,int bb)1440*e4b17023SJohn Marino find_bypass_set (int regno, int bb)
1441*e4b17023SJohn Marino {
1442*e4b17023SJohn Marino   struct expr *result = 0;
1443*e4b17023SJohn Marino 
1444*e4b17023SJohn Marino   for (;;)
1445*e4b17023SJohn Marino     {
1446*e4b17023SJohn Marino       rtx src;
1447*e4b17023SJohn Marino       struct expr *set = lookup_set (regno, &set_hash_table);
1448*e4b17023SJohn Marino 
1449*e4b17023SJohn Marino       while (set)
1450*e4b17023SJohn Marino 	{
1451*e4b17023SJohn Marino 	  if (TEST_BIT (cprop_avout[bb], set->bitmap_index))
1452*e4b17023SJohn Marino 	    break;
1453*e4b17023SJohn Marino 	  set = next_set (regno, set);
1454*e4b17023SJohn Marino 	}
1455*e4b17023SJohn Marino 
1456*e4b17023SJohn Marino       if (set == 0)
1457*e4b17023SJohn Marino 	break;
1458*e4b17023SJohn Marino 
1459*e4b17023SJohn Marino       src = set->src;
1460*e4b17023SJohn Marino       if (cprop_constant_p (src))
1461*e4b17023SJohn Marino 	result = set;
1462*e4b17023SJohn Marino 
1463*e4b17023SJohn Marino       if (! REG_P (src))
1464*e4b17023SJohn Marino 	break;
1465*e4b17023SJohn Marino 
1466*e4b17023SJohn Marino       regno = REGNO (src);
1467*e4b17023SJohn Marino     }
1468*e4b17023SJohn Marino   return result;
1469*e4b17023SJohn Marino }
1470*e4b17023SJohn Marino 
1471*e4b17023SJohn Marino /* Subroutine of bypass_block that checks whether a pseudo is killed by
1472*e4b17023SJohn Marino    any of the instructions inserted on an edge.  Jump bypassing places
1473*e4b17023SJohn Marino    condition code setters on CFG edges using insert_insn_on_edge.  This
1474*e4b17023SJohn Marino    function is required to check that our data flow analysis is still
1475*e4b17023SJohn Marino    valid prior to commit_edge_insertions.  */
1476*e4b17023SJohn Marino 
1477*e4b17023SJohn Marino static bool
reg_killed_on_edge(const_rtx reg,const_edge e)1478*e4b17023SJohn Marino reg_killed_on_edge (const_rtx reg, const_edge e)
1479*e4b17023SJohn Marino {
1480*e4b17023SJohn Marino   rtx insn;
1481*e4b17023SJohn Marino 
1482*e4b17023SJohn Marino   for (insn = e->insns.r; insn; insn = NEXT_INSN (insn))
1483*e4b17023SJohn Marino     if (INSN_P (insn) && reg_set_p (reg, insn))
1484*e4b17023SJohn Marino       return true;
1485*e4b17023SJohn Marino 
1486*e4b17023SJohn Marino   return false;
1487*e4b17023SJohn Marino }
1488*e4b17023SJohn Marino 
1489*e4b17023SJohn Marino /* Subroutine of bypass_conditional_jumps that attempts to bypass the given
1490*e4b17023SJohn Marino    basic block BB which has more than one predecessor.  If not NULL, SETCC
1491*e4b17023SJohn Marino    is the first instruction of BB, which is immediately followed by JUMP_INSN
1492*e4b17023SJohn Marino    JUMP.  Otherwise, SETCC is NULL, and JUMP is the first insn of BB.
1493*e4b17023SJohn Marino    Returns nonzero if a change was made.
1494*e4b17023SJohn Marino 
1495*e4b17023SJohn Marino    During the jump bypassing pass, we may place copies of SETCC instructions
1496*e4b17023SJohn Marino    on CFG edges.  The following routine must be careful to pay attention to
1497*e4b17023SJohn Marino    these inserted insns when performing its transformations.  */
1498*e4b17023SJohn Marino 
1499*e4b17023SJohn Marino static int
bypass_block(basic_block bb,rtx setcc,rtx jump)1500*e4b17023SJohn Marino bypass_block (basic_block bb, rtx setcc, rtx jump)
1501*e4b17023SJohn Marino {
1502*e4b17023SJohn Marino   rtx insn, note;
1503*e4b17023SJohn Marino   edge e, edest;
1504*e4b17023SJohn Marino   int change;
1505*e4b17023SJohn Marino   int may_be_loop_header;
1506*e4b17023SJohn Marino   unsigned removed_p;
1507*e4b17023SJohn Marino   unsigned i;
1508*e4b17023SJohn Marino   edge_iterator ei;
1509*e4b17023SJohn Marino 
1510*e4b17023SJohn Marino   insn = (setcc != NULL) ? setcc : jump;
1511*e4b17023SJohn Marino 
1512*e4b17023SJohn Marino   /* Determine set of register uses in INSN.  */
1513*e4b17023SJohn Marino   reg_use_count = 0;
1514*e4b17023SJohn Marino   note_uses (&PATTERN (insn), find_used_regs, NULL);
1515*e4b17023SJohn Marino   note = find_reg_equal_equiv_note (insn);
1516*e4b17023SJohn Marino   if (note)
1517*e4b17023SJohn Marino     find_used_regs (&XEXP (note, 0), NULL);
1518*e4b17023SJohn Marino 
1519*e4b17023SJohn Marino   may_be_loop_header = false;
1520*e4b17023SJohn Marino   FOR_EACH_EDGE (e, ei, bb->preds)
1521*e4b17023SJohn Marino     if (e->flags & EDGE_DFS_BACK)
1522*e4b17023SJohn Marino       {
1523*e4b17023SJohn Marino 	may_be_loop_header = true;
1524*e4b17023SJohn Marino 	break;
1525*e4b17023SJohn Marino       }
1526*e4b17023SJohn Marino 
1527*e4b17023SJohn Marino   change = 0;
1528*e4b17023SJohn Marino   for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
1529*e4b17023SJohn Marino     {
1530*e4b17023SJohn Marino       removed_p = 0;
1531*e4b17023SJohn Marino 
1532*e4b17023SJohn Marino       if (e->flags & EDGE_COMPLEX)
1533*e4b17023SJohn Marino 	{
1534*e4b17023SJohn Marino 	  ei_next (&ei);
1535*e4b17023SJohn Marino 	  continue;
1536*e4b17023SJohn Marino 	}
1537*e4b17023SJohn Marino 
1538*e4b17023SJohn Marino       /* We can't redirect edges from new basic blocks.  */
1539*e4b17023SJohn Marino       if (e->src->index >= bypass_last_basic_block)
1540*e4b17023SJohn Marino 	{
1541*e4b17023SJohn Marino 	  ei_next (&ei);
1542*e4b17023SJohn Marino 	  continue;
1543*e4b17023SJohn Marino 	}
1544*e4b17023SJohn Marino 
1545*e4b17023SJohn Marino       /* The irreducible loops created by redirecting of edges entering the
1546*e4b17023SJohn Marino 	 loop from outside would decrease effectiveness of some of the
1547*e4b17023SJohn Marino 	 following optimizations, so prevent this.  */
1548*e4b17023SJohn Marino       if (may_be_loop_header
1549*e4b17023SJohn Marino 	  && !(e->flags & EDGE_DFS_BACK))
1550*e4b17023SJohn Marino 	{
1551*e4b17023SJohn Marino 	  ei_next (&ei);
1552*e4b17023SJohn Marino 	  continue;
1553*e4b17023SJohn Marino 	}
1554*e4b17023SJohn Marino 
1555*e4b17023SJohn Marino       for (i = 0; i < reg_use_count; i++)
1556*e4b17023SJohn Marino 	{
1557*e4b17023SJohn Marino 	  rtx reg_used = reg_use_table[i];
1558*e4b17023SJohn Marino 	  unsigned int regno = REGNO (reg_used);
1559*e4b17023SJohn Marino 	  basic_block dest, old_dest;
1560*e4b17023SJohn Marino 	  struct expr *set;
1561*e4b17023SJohn Marino 	  rtx src, new_rtx;
1562*e4b17023SJohn Marino 
1563*e4b17023SJohn Marino 	  set = find_bypass_set (regno, e->src->index);
1564*e4b17023SJohn Marino 
1565*e4b17023SJohn Marino 	  if (! set)
1566*e4b17023SJohn Marino 	    continue;
1567*e4b17023SJohn Marino 
1568*e4b17023SJohn Marino 	  /* Check the data flow is valid after edge insertions.  */
1569*e4b17023SJohn Marino 	  if (e->insns.r && reg_killed_on_edge (reg_used, e))
1570*e4b17023SJohn Marino 	    continue;
1571*e4b17023SJohn Marino 
1572*e4b17023SJohn Marino 	  src = SET_SRC (pc_set (jump));
1573*e4b17023SJohn Marino 
1574*e4b17023SJohn Marino 	  if (setcc != NULL)
1575*e4b17023SJohn Marino 	    src = simplify_replace_rtx (src,
1576*e4b17023SJohn Marino 					SET_DEST (PATTERN (setcc)),
1577*e4b17023SJohn Marino 					SET_SRC (PATTERN (setcc)));
1578*e4b17023SJohn Marino 
1579*e4b17023SJohn Marino 	  new_rtx = simplify_replace_rtx (src, reg_used, set->src);
1580*e4b17023SJohn Marino 
1581*e4b17023SJohn Marino 	  /* Jump bypassing may have already placed instructions on
1582*e4b17023SJohn Marino 	     edges of the CFG.  We can't bypass an outgoing edge that
1583*e4b17023SJohn Marino 	     has instructions associated with it, as these insns won't
1584*e4b17023SJohn Marino 	     get executed if the incoming edge is redirected.  */
1585*e4b17023SJohn Marino 	  if (new_rtx == pc_rtx)
1586*e4b17023SJohn Marino 	    {
1587*e4b17023SJohn Marino 	      edest = FALLTHRU_EDGE (bb);
1588*e4b17023SJohn Marino 	      dest = edest->insns.r ? NULL : edest->dest;
1589*e4b17023SJohn Marino 	    }
1590*e4b17023SJohn Marino 	  else if (GET_CODE (new_rtx) == LABEL_REF)
1591*e4b17023SJohn Marino 	    {
1592*e4b17023SJohn Marino 	      dest = BLOCK_FOR_INSN (XEXP (new_rtx, 0));
1593*e4b17023SJohn Marino 	      /* Don't bypass edges containing instructions.  */
1594*e4b17023SJohn Marino 	      edest = find_edge (bb, dest);
1595*e4b17023SJohn Marino 	      if (edest && edest->insns.r)
1596*e4b17023SJohn Marino 		dest = NULL;
1597*e4b17023SJohn Marino 	    }
1598*e4b17023SJohn Marino 	  else
1599*e4b17023SJohn Marino 	    dest = NULL;
1600*e4b17023SJohn Marino 
1601*e4b17023SJohn Marino 	  /* Avoid unification of the edge with other edges from original
1602*e4b17023SJohn Marino 	     branch.  We would end up emitting the instruction on "both"
1603*e4b17023SJohn Marino 	     edges.  */
1604*e4b17023SJohn Marino 	  if (dest && setcc && !CC0_P (SET_DEST (PATTERN (setcc)))
1605*e4b17023SJohn Marino 	      && find_edge (e->src, dest))
1606*e4b17023SJohn Marino 	    dest = NULL;
1607*e4b17023SJohn Marino 
1608*e4b17023SJohn Marino 	  old_dest = e->dest;
1609*e4b17023SJohn Marino 	  if (dest != NULL
1610*e4b17023SJohn Marino 	      && dest != old_dest
1611*e4b17023SJohn Marino 	      && dest != EXIT_BLOCK_PTR)
1612*e4b17023SJohn Marino             {
1613*e4b17023SJohn Marino 	      redirect_edge_and_branch_force (e, dest);
1614*e4b17023SJohn Marino 
1615*e4b17023SJohn Marino 	      /* Copy the register setter to the redirected edge.
1616*e4b17023SJohn Marino 		 Don't copy CC0 setters, as CC0 is dead after jump.  */
1617*e4b17023SJohn Marino 	      if (setcc)
1618*e4b17023SJohn Marino 		{
1619*e4b17023SJohn Marino 		  rtx pat = PATTERN (setcc);
1620*e4b17023SJohn Marino 		  if (!CC0_P (SET_DEST (pat)))
1621*e4b17023SJohn Marino 		    insert_insn_on_edge (copy_insn (pat), e);
1622*e4b17023SJohn Marino 		}
1623*e4b17023SJohn Marino 
1624*e4b17023SJohn Marino 	      if (dump_file != NULL)
1625*e4b17023SJohn Marino 		{
1626*e4b17023SJohn Marino 		  fprintf (dump_file, "JUMP-BYPASS: Proved reg %d "
1627*e4b17023SJohn Marino 				      "in jump_insn %d equals constant ",
1628*e4b17023SJohn Marino 			   regno, INSN_UID (jump));
1629*e4b17023SJohn Marino 		  print_rtl (dump_file, set->src);
1630*e4b17023SJohn Marino 		  fprintf (dump_file, "\nBypass edge from %d->%d to %d\n",
1631*e4b17023SJohn Marino 			   e->src->index, old_dest->index, dest->index);
1632*e4b17023SJohn Marino 		}
1633*e4b17023SJohn Marino 	      change = 1;
1634*e4b17023SJohn Marino 	      removed_p = 1;
1635*e4b17023SJohn Marino 	      break;
1636*e4b17023SJohn Marino 	    }
1637*e4b17023SJohn Marino 	}
1638*e4b17023SJohn Marino       if (!removed_p)
1639*e4b17023SJohn Marino 	ei_next (&ei);
1640*e4b17023SJohn Marino     }
1641*e4b17023SJohn Marino   return change;
1642*e4b17023SJohn Marino }
1643*e4b17023SJohn Marino 
1644*e4b17023SJohn Marino /* Find basic blocks with more than one predecessor that only contain a
1645*e4b17023SJohn Marino    single conditional jump.  If the result of the comparison is known at
1646*e4b17023SJohn Marino    compile-time from any incoming edge, redirect that edge to the
1647*e4b17023SJohn Marino    appropriate target.  Return nonzero if a change was made.
1648*e4b17023SJohn Marino 
1649*e4b17023SJohn Marino    This function is now mis-named, because we also handle indirect jumps.  */
1650*e4b17023SJohn Marino 
1651*e4b17023SJohn Marino static int
bypass_conditional_jumps(void)1652*e4b17023SJohn Marino bypass_conditional_jumps (void)
1653*e4b17023SJohn Marino {
1654*e4b17023SJohn Marino   basic_block bb;
1655*e4b17023SJohn Marino   int changed;
1656*e4b17023SJohn Marino   rtx setcc;
1657*e4b17023SJohn Marino   rtx insn;
1658*e4b17023SJohn Marino   rtx dest;
1659*e4b17023SJohn Marino 
1660*e4b17023SJohn Marino   /* Note we start at block 1.  */
1661*e4b17023SJohn Marino   if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR)
1662*e4b17023SJohn Marino     return 0;
1663*e4b17023SJohn Marino 
1664*e4b17023SJohn Marino   bypass_last_basic_block = last_basic_block;
1665*e4b17023SJohn Marino   mark_dfs_back_edges ();
1666*e4b17023SJohn Marino 
1667*e4b17023SJohn Marino   changed = 0;
1668*e4b17023SJohn Marino   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb,
1669*e4b17023SJohn Marino 		  EXIT_BLOCK_PTR, next_bb)
1670*e4b17023SJohn Marino     {
1671*e4b17023SJohn Marino       /* Check for more than one predecessor.  */
1672*e4b17023SJohn Marino       if (!single_pred_p (bb))
1673*e4b17023SJohn Marino 	{
1674*e4b17023SJohn Marino 	  setcc = NULL_RTX;
1675*e4b17023SJohn Marino 	  FOR_BB_INSNS (bb, insn)
1676*e4b17023SJohn Marino 	    if (DEBUG_INSN_P (insn))
1677*e4b17023SJohn Marino 	      continue;
1678*e4b17023SJohn Marino 	    else if (NONJUMP_INSN_P (insn))
1679*e4b17023SJohn Marino 	      {
1680*e4b17023SJohn Marino 		if (setcc)
1681*e4b17023SJohn Marino 		  break;
1682*e4b17023SJohn Marino 		if (GET_CODE (PATTERN (insn)) != SET)
1683*e4b17023SJohn Marino 		  break;
1684*e4b17023SJohn Marino 
1685*e4b17023SJohn Marino 		dest = SET_DEST (PATTERN (insn));
1686*e4b17023SJohn Marino 		if (REG_P (dest) || CC0_P (dest))
1687*e4b17023SJohn Marino 		  setcc = insn;
1688*e4b17023SJohn Marino 		else
1689*e4b17023SJohn Marino 		  break;
1690*e4b17023SJohn Marino 	      }
1691*e4b17023SJohn Marino 	    else if (JUMP_P (insn))
1692*e4b17023SJohn Marino 	      {
1693*e4b17023SJohn Marino 		if ((any_condjump_p (insn) || computed_jump_p (insn))
1694*e4b17023SJohn Marino 		    && onlyjump_p (insn))
1695*e4b17023SJohn Marino 		  changed |= bypass_block (bb, setcc, insn);
1696*e4b17023SJohn Marino 		break;
1697*e4b17023SJohn Marino 	      }
1698*e4b17023SJohn Marino 	    else if (INSN_P (insn))
1699*e4b17023SJohn Marino 	      break;
1700*e4b17023SJohn Marino 	}
1701*e4b17023SJohn Marino     }
1702*e4b17023SJohn Marino 
1703*e4b17023SJohn Marino   /* If we bypassed any register setting insns, we inserted a
1704*e4b17023SJohn Marino      copy on the redirected edge.  These need to be committed.  */
1705*e4b17023SJohn Marino   if (changed)
1706*e4b17023SJohn Marino     commit_edge_insertions ();
1707*e4b17023SJohn Marino 
1708*e4b17023SJohn Marino   return changed;
1709*e4b17023SJohn Marino }
1710*e4b17023SJohn Marino 
1711*e4b17023SJohn Marino /* Return true if the graph is too expensive to optimize.  PASS is the
1712*e4b17023SJohn Marino    optimization about to be performed.  */
1713*e4b17023SJohn Marino 
1714*e4b17023SJohn Marino static bool
is_too_expensive(const char * pass)1715*e4b17023SJohn Marino is_too_expensive (const char *pass)
1716*e4b17023SJohn Marino {
1717*e4b17023SJohn Marino   /* Trying to perform global optimizations on flow graphs which have
1718*e4b17023SJohn Marino      a high connectivity will take a long time and is unlikely to be
1719*e4b17023SJohn Marino      particularly useful.
1720*e4b17023SJohn Marino 
1721*e4b17023SJohn Marino      In normal circumstances a cfg should have about twice as many
1722*e4b17023SJohn Marino      edges as blocks.  But we do not want to punish small functions
1723*e4b17023SJohn Marino      which have a couple switch statements.  Rather than simply
1724*e4b17023SJohn Marino      threshold the number of blocks, uses something with a more
1725*e4b17023SJohn Marino      graceful degradation.  */
1726*e4b17023SJohn Marino   if (n_edges > 20000 + n_basic_blocks * 4)
1727*e4b17023SJohn Marino     {
1728*e4b17023SJohn Marino       warning (OPT_Wdisabled_optimization,
1729*e4b17023SJohn Marino 	       "%s: %d basic blocks and %d edges/basic block",
1730*e4b17023SJohn Marino 	       pass, n_basic_blocks, n_edges / n_basic_blocks);
1731*e4b17023SJohn Marino 
1732*e4b17023SJohn Marino       return true;
1733*e4b17023SJohn Marino     }
1734*e4b17023SJohn Marino 
1735*e4b17023SJohn Marino   /* If allocating memory for the cprop bitmap would take up too much
1736*e4b17023SJohn Marino      storage it's better just to disable the optimization.  */
1737*e4b17023SJohn Marino   if ((n_basic_blocks
1738*e4b17023SJohn Marino        * SBITMAP_SET_SIZE (max_reg_num ())
1739*e4b17023SJohn Marino        * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY)
1740*e4b17023SJohn Marino     {
1741*e4b17023SJohn Marino       warning (OPT_Wdisabled_optimization,
1742*e4b17023SJohn Marino 	       "%s: %d basic blocks and %d registers",
1743*e4b17023SJohn Marino 	       pass, n_basic_blocks, max_reg_num ());
1744*e4b17023SJohn Marino 
1745*e4b17023SJohn Marino       return true;
1746*e4b17023SJohn Marino     }
1747*e4b17023SJohn Marino 
1748*e4b17023SJohn Marino   return false;
1749*e4b17023SJohn Marino }
1750*e4b17023SJohn Marino 
1751*e4b17023SJohn Marino /* Main function for the CPROP pass.  */
1752*e4b17023SJohn Marino 
1753*e4b17023SJohn Marino static int
one_cprop_pass(void)1754*e4b17023SJohn Marino one_cprop_pass (void)
1755*e4b17023SJohn Marino {
1756*e4b17023SJohn Marino   int i;
1757*e4b17023SJohn Marino   int changed = 0;
1758*e4b17023SJohn Marino 
1759*e4b17023SJohn Marino   /* Return if there's nothing to do, or it is too expensive.  */
1760*e4b17023SJohn Marino   if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1
1761*e4b17023SJohn Marino       || is_too_expensive (_ ("const/copy propagation disabled")))
1762*e4b17023SJohn Marino     return 0;
1763*e4b17023SJohn Marino 
1764*e4b17023SJohn Marino   global_const_prop_count = local_const_prop_count = 0;
1765*e4b17023SJohn Marino   global_copy_prop_count = local_copy_prop_count = 0;
1766*e4b17023SJohn Marino 
1767*e4b17023SJohn Marino   bytes_used = 0;
1768*e4b17023SJohn Marino   gcc_obstack_init (&cprop_obstack);
1769*e4b17023SJohn Marino 
1770*e4b17023SJohn Marino   /* Do a local const/copy propagation pass first.  The global pass
1771*e4b17023SJohn Marino      only handles global opportunities.
1772*e4b17023SJohn Marino      If the local pass changes something, remove any unreachable blocks
1773*e4b17023SJohn Marino      because the CPROP global dataflow analysis may get into infinite
1774*e4b17023SJohn Marino      loops for CFGs with unreachable blocks.
1775*e4b17023SJohn Marino 
1776*e4b17023SJohn Marino      FIXME: This local pass should not be necessary after CSE (but for
1777*e4b17023SJohn Marino 	    some reason it still is).  It is also (proven) not necessary
1778*e4b17023SJohn Marino 	    to run the local pass right after FWPWOP.
1779*e4b17023SJohn Marino 
1780*e4b17023SJohn Marino      FIXME: The global analysis would not get into infinite loops if it
1781*e4b17023SJohn Marino 	    would use the DF solver (via df_simple_dataflow) instead of
1782*e4b17023SJohn Marino 	    the solver implemented in this file.  */
1783*e4b17023SJohn Marino   changed |= local_cprop_pass ();
1784*e4b17023SJohn Marino   if (changed)
1785*e4b17023SJohn Marino     delete_unreachable_blocks ();
1786*e4b17023SJohn Marino 
1787*e4b17023SJohn Marino   /* Determine implicit sets.  This may change the CFG (split critical
1788*e4b17023SJohn Marino      edges if that exposes an implicit set).
1789*e4b17023SJohn Marino      Note that find_implicit_sets() does not rely on up-to-date DF caches
1790*e4b17023SJohn Marino      so that we do not have to re-run df_analyze() even if local CPROP
1791*e4b17023SJohn Marino      changed something.
1792*e4b17023SJohn Marino      ??? This could run earlier so that any uncovered implicit sets
1793*e4b17023SJohn Marino 	 sets could be exploited in local_cprop_pass() also.  Later.  */
1794*e4b17023SJohn Marino   changed |= find_implicit_sets ();
1795*e4b17023SJohn Marino 
1796*e4b17023SJohn Marino   /* If local_cprop_pass() or find_implicit_sets() changed something,
1797*e4b17023SJohn Marino      run df_analyze() to bring all insn caches up-to-date, and to take
1798*e4b17023SJohn Marino      new basic blocks from edge splitting on the DF radar.
1799*e4b17023SJohn Marino      NB: This also runs the fast DCE pass, because execute_rtl_cprop
1800*e4b17023SJohn Marino      sets DF_LR_RUN_DCE.  */
1801*e4b17023SJohn Marino   if (changed)
1802*e4b17023SJohn Marino     df_analyze ();
1803*e4b17023SJohn Marino 
1804*e4b17023SJohn Marino   /* Initialize implicit_set_indexes array.  */
1805*e4b17023SJohn Marino   implicit_set_indexes = XNEWVEC (int, last_basic_block);
1806*e4b17023SJohn Marino   for (i = 0; i < last_basic_block; i++)
1807*e4b17023SJohn Marino     implicit_set_indexes[i] = -1;
1808*e4b17023SJohn Marino 
1809*e4b17023SJohn Marino   alloc_hash_table (&set_hash_table);
1810*e4b17023SJohn Marino   compute_hash_table (&set_hash_table);
1811*e4b17023SJohn Marino 
1812*e4b17023SJohn Marino   /* Free implicit_sets before peak usage.  */
1813*e4b17023SJohn Marino   free (implicit_sets);
1814*e4b17023SJohn Marino   implicit_sets = NULL;
1815*e4b17023SJohn Marino 
1816*e4b17023SJohn Marino   if (dump_file)
1817*e4b17023SJohn Marino     dump_hash_table (dump_file, "SET", &set_hash_table);
1818*e4b17023SJohn Marino   if (set_hash_table.n_elems > 0)
1819*e4b17023SJohn Marino     {
1820*e4b17023SJohn Marino       basic_block bb;
1821*e4b17023SJohn Marino       rtx insn;
1822*e4b17023SJohn Marino 
1823*e4b17023SJohn Marino       alloc_cprop_mem (last_basic_block, set_hash_table.n_elems);
1824*e4b17023SJohn Marino       compute_cprop_data ();
1825*e4b17023SJohn Marino 
1826*e4b17023SJohn Marino       free (implicit_set_indexes);
1827*e4b17023SJohn Marino       implicit_set_indexes = NULL;
1828*e4b17023SJohn Marino 
1829*e4b17023SJohn Marino       /* Allocate vars to track sets of regs.  */
1830*e4b17023SJohn Marino       reg_set_bitmap = ALLOC_REG_SET (NULL);
1831*e4b17023SJohn Marino 
1832*e4b17023SJohn Marino       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR,
1833*e4b17023SJohn Marino 		      next_bb)
1834*e4b17023SJohn Marino 	{
1835*e4b17023SJohn Marino 	  /* Reset tables used to keep track of what's still valid [since
1836*e4b17023SJohn Marino 	     the start of the block].  */
1837*e4b17023SJohn Marino 	  reset_opr_set_tables ();
1838*e4b17023SJohn Marino 
1839*e4b17023SJohn Marino 	  FOR_BB_INSNS (bb, insn)
1840*e4b17023SJohn Marino 	    if (INSN_P (insn))
1841*e4b17023SJohn Marino 	      {
1842*e4b17023SJohn Marino 		changed |= cprop_insn (insn);
1843*e4b17023SJohn Marino 
1844*e4b17023SJohn Marino 		/* Keep track of everything modified by this insn.  */
1845*e4b17023SJohn Marino 		/* ??? Need to be careful w.r.t. mods done to INSN.
1846*e4b17023SJohn Marino 		       Don't call mark_oprs_set if we turned the
1847*e4b17023SJohn Marino 		       insn into a NOTE, or deleted the insn.  */
1848*e4b17023SJohn Marino 		if (! NOTE_P (insn) && ! INSN_DELETED_P (insn))
1849*e4b17023SJohn Marino 		  mark_oprs_set (insn);
1850*e4b17023SJohn Marino 	      }
1851*e4b17023SJohn Marino 	}
1852*e4b17023SJohn Marino 
1853*e4b17023SJohn Marino       changed |= bypass_conditional_jumps ();
1854*e4b17023SJohn Marino 
1855*e4b17023SJohn Marino       FREE_REG_SET (reg_set_bitmap);
1856*e4b17023SJohn Marino       free_cprop_mem ();
1857*e4b17023SJohn Marino     }
1858*e4b17023SJohn Marino   else
1859*e4b17023SJohn Marino     {
1860*e4b17023SJohn Marino       free (implicit_set_indexes);
1861*e4b17023SJohn Marino       implicit_set_indexes = NULL;
1862*e4b17023SJohn Marino     }
1863*e4b17023SJohn Marino 
1864*e4b17023SJohn Marino   free_hash_table (&set_hash_table);
1865*e4b17023SJohn Marino   obstack_free (&cprop_obstack, NULL);
1866*e4b17023SJohn Marino 
1867*e4b17023SJohn Marino   if (dump_file)
1868*e4b17023SJohn Marino     {
1869*e4b17023SJohn Marino       fprintf (dump_file, "CPROP of %s, %d basic blocks, %d bytes needed, ",
1870*e4b17023SJohn Marino 	       current_function_name (), n_basic_blocks, bytes_used);
1871*e4b17023SJohn Marino       fprintf (dump_file, "%d local const props, %d local copy props, ",
1872*e4b17023SJohn Marino 	       local_const_prop_count, local_copy_prop_count);
1873*e4b17023SJohn Marino       fprintf (dump_file, "%d global const props, %d global copy props\n\n",
1874*e4b17023SJohn Marino 	       global_const_prop_count, global_copy_prop_count);
1875*e4b17023SJohn Marino     }
1876*e4b17023SJohn Marino 
1877*e4b17023SJohn Marino   return changed;
1878*e4b17023SJohn Marino }
1879*e4b17023SJohn Marino 
1880*e4b17023SJohn Marino /* All the passes implemented in this file.  Each pass has its
1881*e4b17023SJohn Marino    own gate and execute function, and at the end of the file a
1882*e4b17023SJohn Marino    pass definition for passes.c.
1883*e4b17023SJohn Marino 
1884*e4b17023SJohn Marino    We do not construct an accurate cfg in functions which call
1885*e4b17023SJohn Marino    setjmp, so none of these passes runs if the function calls
1886*e4b17023SJohn Marino    setjmp.
1887*e4b17023SJohn Marino    FIXME: Should just handle setjmp via REG_SETJMP notes.  */
1888*e4b17023SJohn Marino 
1889*e4b17023SJohn Marino static bool
gate_rtl_cprop(void)1890*e4b17023SJohn Marino gate_rtl_cprop (void)
1891*e4b17023SJohn Marino {
1892*e4b17023SJohn Marino   return optimize > 0 && flag_gcse
1893*e4b17023SJohn Marino     && !cfun->calls_setjmp
1894*e4b17023SJohn Marino     && dbg_cnt (cprop);
1895*e4b17023SJohn Marino }
1896*e4b17023SJohn Marino 
1897*e4b17023SJohn Marino static unsigned int
execute_rtl_cprop(void)1898*e4b17023SJohn Marino execute_rtl_cprop (void)
1899*e4b17023SJohn Marino {
1900*e4b17023SJohn Marino   int changed;
1901*e4b17023SJohn Marino   delete_unreachable_blocks ();
1902*e4b17023SJohn Marino   df_set_flags (DF_LR_RUN_DCE);
1903*e4b17023SJohn Marino   df_analyze ();
1904*e4b17023SJohn Marino   changed = one_cprop_pass ();
1905*e4b17023SJohn Marino   flag_rerun_cse_after_global_opts |= changed;
1906*e4b17023SJohn Marino   if (changed)
1907*e4b17023SJohn Marino     cleanup_cfg (0);
1908*e4b17023SJohn Marino   return 0;
1909*e4b17023SJohn Marino }
1910*e4b17023SJohn Marino 
1911*e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_cprop =
1912*e4b17023SJohn Marino {
1913*e4b17023SJohn Marino  {
1914*e4b17023SJohn Marino   RTL_PASS,
1915*e4b17023SJohn Marino   "cprop",                              /* name */
1916*e4b17023SJohn Marino   gate_rtl_cprop,                       /* gate */
1917*e4b17023SJohn Marino   execute_rtl_cprop,  			/* execute */
1918*e4b17023SJohn Marino   NULL,                                 /* sub */
1919*e4b17023SJohn Marino   NULL,                                 /* next */
1920*e4b17023SJohn Marino   0,                                    /* static_pass_number */
1921*e4b17023SJohn Marino   TV_CPROP,                             /* tv_id */
1922*e4b17023SJohn Marino   PROP_cfglayout,                       /* properties_required */
1923*e4b17023SJohn Marino   0,                                    /* properties_provided */
1924*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
1925*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
1926*e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing |
1927*e4b17023SJohn Marino   TODO_verify_flow | TODO_ggc_collect   /* todo_flags_finish */
1928*e4b17023SJohn Marino  }
1929*e4b17023SJohn Marino };
1930