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