xref: /dflybsd-src/contrib/gcc-4.7/gcc/fwprop.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* RTL-based forward propagation pass for GNU compiler.
2*e4b17023SJohn Marino    Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Paolo Bonzini and Steven Bosscher.
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tm.h"
26*e4b17023SJohn Marino #include "diagnostic-core.h"
27*e4b17023SJohn Marino 
28*e4b17023SJohn Marino #include "sparseset.h"
29*e4b17023SJohn Marino #include "timevar.h"
30*e4b17023SJohn Marino #include "rtl.h"
31*e4b17023SJohn Marino #include "tm_p.h"
32*e4b17023SJohn Marino #include "insn-config.h"
33*e4b17023SJohn Marino #include "recog.h"
34*e4b17023SJohn Marino #include "flags.h"
35*e4b17023SJohn Marino #include "obstack.h"
36*e4b17023SJohn Marino #include "basic-block.h"
37*e4b17023SJohn Marino #include "output.h"
38*e4b17023SJohn Marino #include "df.h"
39*e4b17023SJohn Marino #include "target.h"
40*e4b17023SJohn Marino #include "cfgloop.h"
41*e4b17023SJohn Marino #include "tree-pass.h"
42*e4b17023SJohn Marino #include "domwalk.h"
43*e4b17023SJohn Marino #include "emit-rtl.h"
44*e4b17023SJohn Marino 
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* This pass does simple forward propagation and simplification when an
47*e4b17023SJohn Marino    operand of an insn can only come from a single def.  This pass uses
48*e4b17023SJohn Marino    df.c, so it is global.  However, we only do limited analysis of
49*e4b17023SJohn Marino    available expressions.
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino    1) The pass tries to propagate the source of the def into the use,
52*e4b17023SJohn Marino    and checks if the result is independent of the substituted value.
53*e4b17023SJohn Marino    For example, the high word of a (zero_extend:DI (reg:SI M)) is always
54*e4b17023SJohn Marino    zero, independent of the source register.
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino    In particular, we propagate constants into the use site.  Sometimes
57*e4b17023SJohn Marino    RTL expansion did not put the constant in the same insn on purpose,
58*e4b17023SJohn Marino    to satisfy a predicate, and the result will fail to be recognized;
59*e4b17023SJohn Marino    but this happens rarely and in this case we can still create a
60*e4b17023SJohn Marino    REG_EQUAL note.  For multi-word operations, this
61*e4b17023SJohn Marino 
62*e4b17023SJohn Marino       (set (subreg:SI (reg:DI 120) 0) (const_int 0))
63*e4b17023SJohn Marino       (set (subreg:SI (reg:DI 120) 4) (const_int -1))
64*e4b17023SJohn Marino       (set (subreg:SI (reg:DI 122) 0)
65*e4b17023SJohn Marino          (ior:SI (subreg:SI (reg:DI 119) 0) (subreg:SI (reg:DI 120) 0)))
66*e4b17023SJohn Marino       (set (subreg:SI (reg:DI 122) 4)
67*e4b17023SJohn Marino          (ior:SI (subreg:SI (reg:DI 119) 4) (subreg:SI (reg:DI 120) 4)))
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino    can be simplified to the much simpler
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino       (set (subreg:SI (reg:DI 122) 0) (subreg:SI (reg:DI 119)))
72*e4b17023SJohn Marino       (set (subreg:SI (reg:DI 122) 4) (const_int -1))
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino    This particular propagation is also effective at putting together
75*e4b17023SJohn Marino    complex addressing modes.  We are more aggressive inside MEMs, in
76*e4b17023SJohn Marino    that all definitions are propagated if the use is in a MEM; if the
77*e4b17023SJohn Marino    result is a valid memory address we check address_cost to decide
78*e4b17023SJohn Marino    whether the substitution is worthwhile.
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino    2) The pass propagates register copies.  This is not as effective as
81*e4b17023SJohn Marino    the copy propagation done by CSE's canon_reg, which works by walking
82*e4b17023SJohn Marino    the instruction chain, it can help the other transformations.
83*e4b17023SJohn Marino 
84*e4b17023SJohn Marino    We should consider removing this optimization, and instead reorder the
85*e4b17023SJohn Marino    RTL passes, because GCSE does this transformation too.  With some luck,
86*e4b17023SJohn Marino    the CSE pass at the end of rest_of_handle_gcse could also go away.
87*e4b17023SJohn Marino 
88*e4b17023SJohn Marino    3) The pass looks for paradoxical subregs that are actually unnecessary.
89*e4b17023SJohn Marino    Things like this:
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino      (set (reg:QI 120) (subreg:QI (reg:SI 118) 0))
92*e4b17023SJohn Marino      (set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
93*e4b17023SJohn Marino      (set (reg:SI 122) (plus:SI (subreg:SI (reg:QI 120) 0)
94*e4b17023SJohn Marino                                 (subreg:SI (reg:QI 121) 0)))
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino    are very common on machines that can only do word-sized operations.
97*e4b17023SJohn Marino    For each use of a paradoxical subreg (subreg:WIDER (reg:NARROW N) 0),
98*e4b17023SJohn Marino    if it has a single def and it is (subreg:NARROW (reg:WIDE M) 0),
99*e4b17023SJohn Marino    we can replace the paradoxical subreg with simply (reg:WIDE M).  The
100*e4b17023SJohn Marino    above will simplify this to
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino      (set (reg:QI 120) (subreg:QI (reg:SI 118) 0))
103*e4b17023SJohn Marino      (set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
104*e4b17023SJohn Marino      (set (reg:SI 122) (plus:SI (reg:SI 118) (reg:SI 119)))
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino    where the first two insns are now dead.
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino    We used to use reaching definitions to find which uses have a
109*e4b17023SJohn Marino    single reaching definition (sounds obvious...), but this is too
110*e4b17023SJohn Marino    complex a problem in nasty testcases like PR33928.  Now we use the
111*e4b17023SJohn Marino    multiple definitions problem in df-problems.c.  The similarity
112*e4b17023SJohn Marino    between that problem and SSA form creation is taken further, in
113*e4b17023SJohn Marino    that fwprop does a dominator walk to create its chains; however,
114*e4b17023SJohn Marino    instead of creating a PHI function where multiple definitions meet
115*e4b17023SJohn Marino    I just punt and record only singleton use-def chains, which is
116*e4b17023SJohn Marino    all that is needed by fwprop.  */
117*e4b17023SJohn Marino 
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino static int num_changes;
120*e4b17023SJohn Marino 
121*e4b17023SJohn Marino DEF_VEC_P(df_ref);
122*e4b17023SJohn Marino DEF_VEC_ALLOC_P(df_ref,heap);
123*e4b17023SJohn Marino static VEC(df_ref,heap) *use_def_ref;
124*e4b17023SJohn Marino static VEC(df_ref,heap) *reg_defs;
125*e4b17023SJohn Marino static VEC(df_ref,heap) *reg_defs_stack;
126*e4b17023SJohn Marino 
127*e4b17023SJohn Marino /* The MD bitmaps are trimmed to include only live registers to cut
128*e4b17023SJohn Marino    memory usage on testcases like insn-recog.c.  Track live registers
129*e4b17023SJohn Marino    in the basic block and do not perform forward propagation if the
130*e4b17023SJohn Marino    destination is a dead pseudo occurring in a note.  */
131*e4b17023SJohn Marino static bitmap local_md;
132*e4b17023SJohn Marino static bitmap local_lr;
133*e4b17023SJohn Marino 
134*e4b17023SJohn Marino /* Return the only def in USE's use-def chain, or NULL if there is
135*e4b17023SJohn Marino    more than one def in the chain.  */
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino static inline df_ref
get_def_for_use(df_ref use)138*e4b17023SJohn Marino get_def_for_use (df_ref use)
139*e4b17023SJohn Marino {
140*e4b17023SJohn Marino   return VEC_index (df_ref, use_def_ref, DF_REF_ID (use));
141*e4b17023SJohn Marino }
142*e4b17023SJohn Marino 
143*e4b17023SJohn Marino 
144*e4b17023SJohn Marino /* Update the reg_defs vector with non-partial definitions in DEF_REC.
145*e4b17023SJohn Marino    TOP_FLAG says which artificials uses should be used, when DEF_REC
146*e4b17023SJohn Marino    is an artificial def vector.  LOCAL_MD is modified as after a
147*e4b17023SJohn Marino    df_md_simulate_* function; we do more or less the same processing
148*e4b17023SJohn Marino    done there, so we do not use those functions.  */
149*e4b17023SJohn Marino 
150*e4b17023SJohn Marino #define DF_MD_GEN_FLAGS \
151*e4b17023SJohn Marino 	(DF_REF_PARTIAL | DF_REF_CONDITIONAL | DF_REF_MAY_CLOBBER)
152*e4b17023SJohn Marino 
153*e4b17023SJohn Marino static void
process_defs(df_ref * def_rec,int top_flag)154*e4b17023SJohn Marino process_defs (df_ref *def_rec, int top_flag)
155*e4b17023SJohn Marino {
156*e4b17023SJohn Marino   df_ref def;
157*e4b17023SJohn Marino   while ((def = *def_rec++) != NULL)
158*e4b17023SJohn Marino     {
159*e4b17023SJohn Marino       df_ref curr_def = VEC_index (df_ref, reg_defs, DF_REF_REGNO (def));
160*e4b17023SJohn Marino       unsigned int dregno;
161*e4b17023SJohn Marino 
162*e4b17023SJohn Marino       if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) != top_flag)
163*e4b17023SJohn Marino 	continue;
164*e4b17023SJohn Marino 
165*e4b17023SJohn Marino       dregno = DF_REF_REGNO (def);
166*e4b17023SJohn Marino       if (curr_def)
167*e4b17023SJohn Marino 	VEC_safe_push (df_ref, heap, reg_defs_stack, curr_def);
168*e4b17023SJohn Marino       else
169*e4b17023SJohn Marino 	{
170*e4b17023SJohn Marino 	  /* Do not store anything if "transitioning" from NULL to NULL.  But
171*e4b17023SJohn Marino              otherwise, push a special entry on the stack to tell the
172*e4b17023SJohn Marino 	     leave_block callback that the entry in reg_defs was NULL.  */
173*e4b17023SJohn Marino 	  if (DF_REF_FLAGS (def) & DF_MD_GEN_FLAGS)
174*e4b17023SJohn Marino 	    ;
175*e4b17023SJohn Marino 	  else
176*e4b17023SJohn Marino 	    VEC_safe_push (df_ref, heap, reg_defs_stack, def);
177*e4b17023SJohn Marino 	}
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino       if (DF_REF_FLAGS (def) & DF_MD_GEN_FLAGS)
180*e4b17023SJohn Marino 	{
181*e4b17023SJohn Marino 	  bitmap_set_bit (local_md, dregno);
182*e4b17023SJohn Marino 	  VEC_replace (df_ref, reg_defs, dregno, NULL);
183*e4b17023SJohn Marino 	}
184*e4b17023SJohn Marino       else
185*e4b17023SJohn Marino 	{
186*e4b17023SJohn Marino 	  bitmap_clear_bit (local_md, dregno);
187*e4b17023SJohn Marino 	  VEC_replace (df_ref, reg_defs, dregno, def);
188*e4b17023SJohn Marino 	}
189*e4b17023SJohn Marino     }
190*e4b17023SJohn Marino }
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino 
193*e4b17023SJohn Marino /* Fill the use_def_ref vector with values for the uses in USE_REC,
194*e4b17023SJohn Marino    taking reaching definitions info from LOCAL_MD and REG_DEFS.
195*e4b17023SJohn Marino    TOP_FLAG says which artificials uses should be used, when USE_REC
196*e4b17023SJohn Marino    is an artificial use vector.  */
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino static void
process_uses(df_ref * use_rec,int top_flag)199*e4b17023SJohn Marino process_uses (df_ref *use_rec, int top_flag)
200*e4b17023SJohn Marino {
201*e4b17023SJohn Marino   df_ref use;
202*e4b17023SJohn Marino   while ((use = *use_rec++) != NULL)
203*e4b17023SJohn Marino     if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == top_flag)
204*e4b17023SJohn Marino       {
205*e4b17023SJohn Marino         unsigned int uregno = DF_REF_REGNO (use);
206*e4b17023SJohn Marino         if (VEC_index (df_ref, reg_defs, uregno)
207*e4b17023SJohn Marino 	    && !bitmap_bit_p (local_md, uregno)
208*e4b17023SJohn Marino 	    && bitmap_bit_p (local_lr, uregno))
209*e4b17023SJohn Marino 	  VEC_replace (df_ref, use_def_ref, DF_REF_ID (use),
210*e4b17023SJohn Marino 		       VEC_index (df_ref, reg_defs, uregno));
211*e4b17023SJohn Marino       }
212*e4b17023SJohn Marino }
213*e4b17023SJohn Marino 
214*e4b17023SJohn Marino 
215*e4b17023SJohn Marino static void
single_def_use_enter_block(struct dom_walk_data * walk_data ATTRIBUTE_UNUSED,basic_block bb)216*e4b17023SJohn Marino single_def_use_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
217*e4b17023SJohn Marino 			    basic_block bb)
218*e4b17023SJohn Marino {
219*e4b17023SJohn Marino   int bb_index = bb->index;
220*e4b17023SJohn Marino   struct df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index);
221*e4b17023SJohn Marino   struct df_lr_bb_info *lr_bb_info = df_lr_get_bb_info (bb_index);
222*e4b17023SJohn Marino   rtx insn;
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino   bitmap_copy (local_md, &md_bb_info->in);
225*e4b17023SJohn Marino   bitmap_copy (local_lr, &lr_bb_info->in);
226*e4b17023SJohn Marino 
227*e4b17023SJohn Marino   /* Push a marker for the leave_block callback.  */
228*e4b17023SJohn Marino   VEC_safe_push (df_ref, heap, reg_defs_stack, NULL);
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino   process_uses (df_get_artificial_uses (bb_index), DF_REF_AT_TOP);
231*e4b17023SJohn Marino   process_defs (df_get_artificial_defs (bb_index), DF_REF_AT_TOP);
232*e4b17023SJohn Marino 
233*e4b17023SJohn Marino   /* We don't call df_simulate_initialize_forwards, as it may overestimate
234*e4b17023SJohn Marino      the live registers if there are unused artificial defs.  We prefer
235*e4b17023SJohn Marino      liveness to be underestimated.  */
236*e4b17023SJohn Marino 
237*e4b17023SJohn Marino   FOR_BB_INSNS (bb, insn)
238*e4b17023SJohn Marino     if (INSN_P (insn))
239*e4b17023SJohn Marino       {
240*e4b17023SJohn Marino         unsigned int uid = INSN_UID (insn);
241*e4b17023SJohn Marino         process_uses (DF_INSN_UID_USES (uid), 0);
242*e4b17023SJohn Marino         process_uses (DF_INSN_UID_EQ_USES (uid), 0);
243*e4b17023SJohn Marino         process_defs (DF_INSN_UID_DEFS (uid), 0);
244*e4b17023SJohn Marino 	df_simulate_one_insn_forwards (bb, insn, local_lr);
245*e4b17023SJohn Marino       }
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino   process_uses (df_get_artificial_uses (bb_index), 0);
248*e4b17023SJohn Marino   process_defs (df_get_artificial_defs (bb_index), 0);
249*e4b17023SJohn Marino }
250*e4b17023SJohn Marino 
251*e4b17023SJohn Marino /* Pop the definitions created in this basic block when leaving its
252*e4b17023SJohn Marino    dominated parts.  */
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino static void
single_def_use_leave_block(struct dom_walk_data * walk_data ATTRIBUTE_UNUSED,basic_block bb ATTRIBUTE_UNUSED)255*e4b17023SJohn Marino single_def_use_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
256*e4b17023SJohn Marino 			    basic_block bb ATTRIBUTE_UNUSED)
257*e4b17023SJohn Marino {
258*e4b17023SJohn Marino   df_ref saved_def;
259*e4b17023SJohn Marino   while ((saved_def = VEC_pop (df_ref, reg_defs_stack)) != NULL)
260*e4b17023SJohn Marino     {
261*e4b17023SJohn Marino       unsigned int dregno = DF_REF_REGNO (saved_def);
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino       /* See also process_defs.  */
264*e4b17023SJohn Marino       if (saved_def == VEC_index (df_ref, reg_defs, dregno))
265*e4b17023SJohn Marino 	VEC_replace (df_ref, reg_defs, dregno, NULL);
266*e4b17023SJohn Marino       else
267*e4b17023SJohn Marino 	VEC_replace (df_ref, reg_defs, dregno, saved_def);
268*e4b17023SJohn Marino     }
269*e4b17023SJohn Marino }
270*e4b17023SJohn Marino 
271*e4b17023SJohn Marino 
272*e4b17023SJohn Marino /* Build a vector holding the reaching definitions of uses reached by a
273*e4b17023SJohn Marino    single dominating definition.  */
274*e4b17023SJohn Marino 
275*e4b17023SJohn Marino static void
build_single_def_use_links(void)276*e4b17023SJohn Marino build_single_def_use_links (void)
277*e4b17023SJohn Marino {
278*e4b17023SJohn Marino   struct dom_walk_data walk_data;
279*e4b17023SJohn Marino 
280*e4b17023SJohn Marino   /* We use the multiple definitions problem to compute our restricted
281*e4b17023SJohn Marino      use-def chains.  */
282*e4b17023SJohn Marino   df_set_flags (DF_EQ_NOTES);
283*e4b17023SJohn Marino   df_md_add_problem ();
284*e4b17023SJohn Marino   df_note_add_problem ();
285*e4b17023SJohn Marino   df_analyze ();
286*e4b17023SJohn Marino   df_maybe_reorganize_use_refs (DF_REF_ORDER_BY_INSN_WITH_NOTES);
287*e4b17023SJohn Marino 
288*e4b17023SJohn Marino   use_def_ref = VEC_alloc (df_ref, heap, DF_USES_TABLE_SIZE ());
289*e4b17023SJohn Marino   VEC_safe_grow_cleared (df_ref, heap, use_def_ref, DF_USES_TABLE_SIZE ());
290*e4b17023SJohn Marino 
291*e4b17023SJohn Marino   reg_defs = VEC_alloc (df_ref, heap, max_reg_num ());
292*e4b17023SJohn Marino   VEC_safe_grow_cleared (df_ref, heap, reg_defs, max_reg_num ());
293*e4b17023SJohn Marino 
294*e4b17023SJohn Marino   reg_defs_stack = VEC_alloc (df_ref, heap, n_basic_blocks * 10);
295*e4b17023SJohn Marino   local_md = BITMAP_ALLOC (NULL);
296*e4b17023SJohn Marino   local_lr = BITMAP_ALLOC (NULL);
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino   /* Walk the dominator tree looking for single reaching definitions
299*e4b17023SJohn Marino      dominating the uses.  This is similar to how SSA form is built.  */
300*e4b17023SJohn Marino   walk_data.dom_direction = CDI_DOMINATORS;
301*e4b17023SJohn Marino   walk_data.initialize_block_local_data = NULL;
302*e4b17023SJohn Marino   walk_data.before_dom_children = single_def_use_enter_block;
303*e4b17023SJohn Marino   walk_data.after_dom_children = single_def_use_leave_block;
304*e4b17023SJohn Marino 
305*e4b17023SJohn Marino   init_walk_dominator_tree (&walk_data);
306*e4b17023SJohn Marino   walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
307*e4b17023SJohn Marino   fini_walk_dominator_tree (&walk_data);
308*e4b17023SJohn Marino 
309*e4b17023SJohn Marino   BITMAP_FREE (local_lr);
310*e4b17023SJohn Marino   BITMAP_FREE (local_md);
311*e4b17023SJohn Marino   VEC_free (df_ref, heap, reg_defs);
312*e4b17023SJohn Marino   VEC_free (df_ref, heap, reg_defs_stack);
313*e4b17023SJohn Marino }
314*e4b17023SJohn Marino 
315*e4b17023SJohn Marino 
316*e4b17023SJohn Marino /* Do not try to replace constant addresses or addresses of local and
317*e4b17023SJohn Marino    argument slots.  These MEM expressions are made only once and inserted
318*e4b17023SJohn Marino    in many instructions, as well as being used to control symbol table
319*e4b17023SJohn Marino    output.  It is not safe to clobber them.
320*e4b17023SJohn Marino 
321*e4b17023SJohn Marino    There are some uncommon cases where the address is already in a register
322*e4b17023SJohn Marino    for some reason, but we cannot take advantage of that because we have
323*e4b17023SJohn Marino    no easy way to unshare the MEM.  In addition, looking up all stack
324*e4b17023SJohn Marino    addresses is costly.  */
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino static bool
can_simplify_addr(rtx addr)327*e4b17023SJohn Marino can_simplify_addr (rtx addr)
328*e4b17023SJohn Marino {
329*e4b17023SJohn Marino   rtx reg;
330*e4b17023SJohn Marino 
331*e4b17023SJohn Marino   if (CONSTANT_ADDRESS_P (addr))
332*e4b17023SJohn Marino     return false;
333*e4b17023SJohn Marino 
334*e4b17023SJohn Marino   if (GET_CODE (addr) == PLUS)
335*e4b17023SJohn Marino     reg = XEXP (addr, 0);
336*e4b17023SJohn Marino   else
337*e4b17023SJohn Marino     reg = addr;
338*e4b17023SJohn Marino 
339*e4b17023SJohn Marino   return (!REG_P (reg)
340*e4b17023SJohn Marino 	  || (REGNO (reg) != FRAME_POINTER_REGNUM
341*e4b17023SJohn Marino 	      && REGNO (reg) != HARD_FRAME_POINTER_REGNUM
342*e4b17023SJohn Marino 	      && REGNO (reg) != ARG_POINTER_REGNUM));
343*e4b17023SJohn Marino }
344*e4b17023SJohn Marino 
345*e4b17023SJohn Marino /* Returns a canonical version of X for the address, from the point of view,
346*e4b17023SJohn Marino    that all multiplications are represented as MULT instead of the multiply
347*e4b17023SJohn Marino    by a power of 2 being represented as ASHIFT.
348*e4b17023SJohn Marino 
349*e4b17023SJohn Marino    Every ASHIFT we find has been made by simplify_gen_binary and was not
350*e4b17023SJohn Marino    there before, so it is not shared.  So we can do this in place.  */
351*e4b17023SJohn Marino 
352*e4b17023SJohn Marino static void
canonicalize_address(rtx x)353*e4b17023SJohn Marino canonicalize_address (rtx x)
354*e4b17023SJohn Marino {
355*e4b17023SJohn Marino   for (;;)
356*e4b17023SJohn Marino     switch (GET_CODE (x))
357*e4b17023SJohn Marino       {
358*e4b17023SJohn Marino       case ASHIFT:
359*e4b17023SJohn Marino         if (CONST_INT_P (XEXP (x, 1))
360*e4b17023SJohn Marino             && INTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (GET_MODE (x))
361*e4b17023SJohn Marino             && INTVAL (XEXP (x, 1)) >= 0)
362*e4b17023SJohn Marino 	  {
363*e4b17023SJohn Marino 	    HOST_WIDE_INT shift = INTVAL (XEXP (x, 1));
364*e4b17023SJohn Marino 	    PUT_CODE (x, MULT);
365*e4b17023SJohn Marino 	    XEXP (x, 1) = gen_int_mode ((HOST_WIDE_INT) 1 << shift,
366*e4b17023SJohn Marino 					GET_MODE (x));
367*e4b17023SJohn Marino 	  }
368*e4b17023SJohn Marino 
369*e4b17023SJohn Marino 	x = XEXP (x, 0);
370*e4b17023SJohn Marino         break;
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino       case PLUS:
373*e4b17023SJohn Marino         if (GET_CODE (XEXP (x, 0)) == PLUS
374*e4b17023SJohn Marino 	    || GET_CODE (XEXP (x, 0)) == ASHIFT
375*e4b17023SJohn Marino 	    || GET_CODE (XEXP (x, 0)) == CONST)
376*e4b17023SJohn Marino 	  canonicalize_address (XEXP (x, 0));
377*e4b17023SJohn Marino 
378*e4b17023SJohn Marino 	x = XEXP (x, 1);
379*e4b17023SJohn Marino         break;
380*e4b17023SJohn Marino 
381*e4b17023SJohn Marino       case CONST:
382*e4b17023SJohn Marino 	x = XEXP (x, 0);
383*e4b17023SJohn Marino         break;
384*e4b17023SJohn Marino 
385*e4b17023SJohn Marino       default:
386*e4b17023SJohn Marino         return;
387*e4b17023SJohn Marino       }
388*e4b17023SJohn Marino }
389*e4b17023SJohn Marino 
390*e4b17023SJohn Marino /* OLD is a memory address.  Return whether it is good to use NEW instead,
391*e4b17023SJohn Marino    for a memory access in the given MODE.  */
392*e4b17023SJohn Marino 
393*e4b17023SJohn Marino static bool
should_replace_address(rtx old_rtx,rtx new_rtx,enum machine_mode mode,addr_space_t as,bool speed)394*e4b17023SJohn Marino should_replace_address (rtx old_rtx, rtx new_rtx, enum machine_mode mode,
395*e4b17023SJohn Marino 			addr_space_t as, bool speed)
396*e4b17023SJohn Marino {
397*e4b17023SJohn Marino   int gain;
398*e4b17023SJohn Marino 
399*e4b17023SJohn Marino   if (rtx_equal_p (old_rtx, new_rtx)
400*e4b17023SJohn Marino       || !memory_address_addr_space_p (mode, new_rtx, as))
401*e4b17023SJohn Marino     return false;
402*e4b17023SJohn Marino 
403*e4b17023SJohn Marino   /* Copy propagation is always ok.  */
404*e4b17023SJohn Marino   if (REG_P (old_rtx) && REG_P (new_rtx))
405*e4b17023SJohn Marino     return true;
406*e4b17023SJohn Marino 
407*e4b17023SJohn Marino   /* Prefer the new address if it is less expensive.  */
408*e4b17023SJohn Marino   gain = (address_cost (old_rtx, mode, as, speed)
409*e4b17023SJohn Marino 	  - address_cost (new_rtx, mode, as, speed));
410*e4b17023SJohn Marino 
411*e4b17023SJohn Marino   /* If the addresses have equivalent cost, prefer the new address
412*e4b17023SJohn Marino      if it has the highest `set_src_cost'.  That has the potential of
413*e4b17023SJohn Marino      eliminating the most insns without additional costs, and it
414*e4b17023SJohn Marino      is the same that cse.c used to do.  */
415*e4b17023SJohn Marino   if (gain == 0)
416*e4b17023SJohn Marino     gain = set_src_cost (new_rtx, speed) - set_src_cost (old_rtx, speed);
417*e4b17023SJohn Marino 
418*e4b17023SJohn Marino   return (gain > 0);
419*e4b17023SJohn Marino }
420*e4b17023SJohn Marino 
421*e4b17023SJohn Marino 
422*e4b17023SJohn Marino /* Flags for the last parameter of propagate_rtx_1.  */
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino enum {
425*e4b17023SJohn Marino   /* If PR_CAN_APPEAR is true, propagate_rtx_1 always returns true;
426*e4b17023SJohn Marino      if it is false, propagate_rtx_1 returns false if, for at least
427*e4b17023SJohn Marino      one occurrence OLD, it failed to collapse the result to a constant.
428*e4b17023SJohn Marino      For example, (mult:M (reg:M A) (minus:M (reg:M B) (reg:M A))) may
429*e4b17023SJohn Marino      collapse to zero if replacing (reg:M B) with (reg:M A).
430*e4b17023SJohn Marino 
431*e4b17023SJohn Marino      PR_CAN_APPEAR is disregarded inside MEMs: in that case,
432*e4b17023SJohn Marino      propagate_rtx_1 just tries to make cheaper and valid memory
433*e4b17023SJohn Marino      addresses.  */
434*e4b17023SJohn Marino   PR_CAN_APPEAR = 1,
435*e4b17023SJohn Marino 
436*e4b17023SJohn Marino   /* If PR_HANDLE_MEM is not set, propagate_rtx_1 won't attempt any replacement
437*e4b17023SJohn Marino      outside memory addresses.  This is needed because propagate_rtx_1 does
438*e4b17023SJohn Marino      not do any analysis on memory; thus it is very conservative and in general
439*e4b17023SJohn Marino      it will fail if non-read-only MEMs are found in the source expression.
440*e4b17023SJohn Marino 
441*e4b17023SJohn Marino      PR_HANDLE_MEM is set when the source of the propagation was not
442*e4b17023SJohn Marino      another MEM.  Then, it is safe not to treat non-read-only MEMs as
443*e4b17023SJohn Marino      ``opaque'' objects.  */
444*e4b17023SJohn Marino   PR_HANDLE_MEM = 2,
445*e4b17023SJohn Marino 
446*e4b17023SJohn Marino   /* Set when costs should be optimized for speed.  */
447*e4b17023SJohn Marino   PR_OPTIMIZE_FOR_SPEED = 4
448*e4b17023SJohn Marino };
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino 
451*e4b17023SJohn Marino /* Replace all occurrences of OLD in *PX with NEW and try to simplify the
452*e4b17023SJohn Marino    resulting expression.  Replace *PX with a new RTL expression if an
453*e4b17023SJohn Marino    occurrence of OLD was found.
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino    This is only a wrapper around simplify-rtx.c: do not add any pattern
456*e4b17023SJohn Marino    matching code here.  (The sole exception is the handling of LO_SUM, but
457*e4b17023SJohn Marino    that is because there is no simplify_gen_* function for LO_SUM).  */
458*e4b17023SJohn Marino 
459*e4b17023SJohn Marino static bool
propagate_rtx_1(rtx * px,rtx old_rtx,rtx new_rtx,int flags)460*e4b17023SJohn Marino propagate_rtx_1 (rtx *px, rtx old_rtx, rtx new_rtx, int flags)
461*e4b17023SJohn Marino {
462*e4b17023SJohn Marino   rtx x = *px, tem = NULL_RTX, op0, op1, op2;
463*e4b17023SJohn Marino   enum rtx_code code = GET_CODE (x);
464*e4b17023SJohn Marino   enum machine_mode mode = GET_MODE (x);
465*e4b17023SJohn Marino   enum machine_mode op_mode;
466*e4b17023SJohn Marino   bool can_appear = (flags & PR_CAN_APPEAR) != 0;
467*e4b17023SJohn Marino   bool valid_ops = true;
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino   if (!(flags & PR_HANDLE_MEM) && MEM_P (x) && !MEM_READONLY_P (x))
470*e4b17023SJohn Marino     {
471*e4b17023SJohn Marino       /* If unsafe, change MEMs to CLOBBERs or SCRATCHes (to preserve whether
472*e4b17023SJohn Marino 	 they have side effects or not).  */
473*e4b17023SJohn Marino       *px = (side_effects_p (x)
474*e4b17023SJohn Marino 	     ? gen_rtx_CLOBBER (GET_MODE (x), const0_rtx)
475*e4b17023SJohn Marino 	     : gen_rtx_SCRATCH (GET_MODE (x)));
476*e4b17023SJohn Marino       return false;
477*e4b17023SJohn Marino     }
478*e4b17023SJohn Marino 
479*e4b17023SJohn Marino   /* If X is OLD_RTX, return NEW_RTX.  But not if replacing only within an
480*e4b17023SJohn Marino      address, and we are *not* inside one.  */
481*e4b17023SJohn Marino   if (x == old_rtx)
482*e4b17023SJohn Marino     {
483*e4b17023SJohn Marino       *px = new_rtx;
484*e4b17023SJohn Marino       return can_appear;
485*e4b17023SJohn Marino     }
486*e4b17023SJohn Marino 
487*e4b17023SJohn Marino   /* If this is an expression, try recursive substitution.  */
488*e4b17023SJohn Marino   switch (GET_RTX_CLASS (code))
489*e4b17023SJohn Marino     {
490*e4b17023SJohn Marino     case RTX_UNARY:
491*e4b17023SJohn Marino       op0 = XEXP (x, 0);
492*e4b17023SJohn Marino       op_mode = GET_MODE (op0);
493*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
494*e4b17023SJohn Marino       if (op0 == XEXP (x, 0))
495*e4b17023SJohn Marino 	return true;
496*e4b17023SJohn Marino       tem = simplify_gen_unary (code, mode, op0, op_mode);
497*e4b17023SJohn Marino       break;
498*e4b17023SJohn Marino 
499*e4b17023SJohn Marino     case RTX_BIN_ARITH:
500*e4b17023SJohn Marino     case RTX_COMM_ARITH:
501*e4b17023SJohn Marino       op0 = XEXP (x, 0);
502*e4b17023SJohn Marino       op1 = XEXP (x, 1);
503*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
504*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
505*e4b17023SJohn Marino       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
506*e4b17023SJohn Marino 	return true;
507*e4b17023SJohn Marino       tem = simplify_gen_binary (code, mode, op0, op1);
508*e4b17023SJohn Marino       break;
509*e4b17023SJohn Marino 
510*e4b17023SJohn Marino     case RTX_COMPARE:
511*e4b17023SJohn Marino     case RTX_COMM_COMPARE:
512*e4b17023SJohn Marino       op0 = XEXP (x, 0);
513*e4b17023SJohn Marino       op1 = XEXP (x, 1);
514*e4b17023SJohn Marino       op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
515*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
516*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
517*e4b17023SJohn Marino       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
518*e4b17023SJohn Marino 	return true;
519*e4b17023SJohn Marino       tem = simplify_gen_relational (code, mode, op_mode, op0, op1);
520*e4b17023SJohn Marino       break;
521*e4b17023SJohn Marino 
522*e4b17023SJohn Marino     case RTX_TERNARY:
523*e4b17023SJohn Marino     case RTX_BITFIELD_OPS:
524*e4b17023SJohn Marino       op0 = XEXP (x, 0);
525*e4b17023SJohn Marino       op1 = XEXP (x, 1);
526*e4b17023SJohn Marino       op2 = XEXP (x, 2);
527*e4b17023SJohn Marino       op_mode = GET_MODE (op0);
528*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
529*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
530*e4b17023SJohn Marino       valid_ops &= propagate_rtx_1 (&op2, old_rtx, new_rtx, flags);
531*e4b17023SJohn Marino       if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2))
532*e4b17023SJohn Marino 	return true;
533*e4b17023SJohn Marino       if (op_mode == VOIDmode)
534*e4b17023SJohn Marino 	op_mode = GET_MODE (op0);
535*e4b17023SJohn Marino       tem = simplify_gen_ternary (code, mode, op_mode, op0, op1, op2);
536*e4b17023SJohn Marino       break;
537*e4b17023SJohn Marino 
538*e4b17023SJohn Marino     case RTX_EXTRA:
539*e4b17023SJohn Marino       /* The only case we try to handle is a SUBREG.  */
540*e4b17023SJohn Marino       if (code == SUBREG)
541*e4b17023SJohn Marino 	{
542*e4b17023SJohn Marino           op0 = XEXP (x, 0);
543*e4b17023SJohn Marino 	  valid_ops &= propagate_rtx_1 (&op0, old_rtx, new_rtx, flags);
544*e4b17023SJohn Marino           if (op0 == XEXP (x, 0))
545*e4b17023SJohn Marino 	    return true;
546*e4b17023SJohn Marino 	  tem = simplify_gen_subreg (mode, op0, GET_MODE (SUBREG_REG (x)),
547*e4b17023SJohn Marino 				     SUBREG_BYTE (x));
548*e4b17023SJohn Marino 	}
549*e4b17023SJohn Marino       break;
550*e4b17023SJohn Marino 
551*e4b17023SJohn Marino     case RTX_OBJ:
552*e4b17023SJohn Marino       if (code == MEM && x != new_rtx)
553*e4b17023SJohn Marino 	{
554*e4b17023SJohn Marino 	  rtx new_op0;
555*e4b17023SJohn Marino 	  op0 = XEXP (x, 0);
556*e4b17023SJohn Marino 
557*e4b17023SJohn Marino 	  /* There are some addresses that we cannot work on.  */
558*e4b17023SJohn Marino 	  if (!can_simplify_addr (op0))
559*e4b17023SJohn Marino 	    return true;
560*e4b17023SJohn Marino 
561*e4b17023SJohn Marino 	  op0 = new_op0 = targetm.delegitimize_address (op0);
562*e4b17023SJohn Marino 	  valid_ops &= propagate_rtx_1 (&new_op0, old_rtx, new_rtx,
563*e4b17023SJohn Marino 					flags | PR_CAN_APPEAR);
564*e4b17023SJohn Marino 
565*e4b17023SJohn Marino 	  /* Dismiss transformation that we do not want to carry on.  */
566*e4b17023SJohn Marino 	  if (!valid_ops
567*e4b17023SJohn Marino 	      || new_op0 == op0
568*e4b17023SJohn Marino 	      || !(GET_MODE (new_op0) == GET_MODE (op0)
569*e4b17023SJohn Marino 		   || GET_MODE (new_op0) == VOIDmode))
570*e4b17023SJohn Marino 	    return true;
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino 	  canonicalize_address (new_op0);
573*e4b17023SJohn Marino 
574*e4b17023SJohn Marino 	  /* Copy propagations are always ok.  Otherwise check the costs.  */
575*e4b17023SJohn Marino 	  if (!(REG_P (old_rtx) && REG_P (new_rtx))
576*e4b17023SJohn Marino 	      && !should_replace_address (op0, new_op0, GET_MODE (x),
577*e4b17023SJohn Marino 					  MEM_ADDR_SPACE (x),
578*e4b17023SJohn Marino 	      			 	  flags & PR_OPTIMIZE_FOR_SPEED))
579*e4b17023SJohn Marino 	    return true;
580*e4b17023SJohn Marino 
581*e4b17023SJohn Marino 	  tem = replace_equiv_address_nv (x, new_op0);
582*e4b17023SJohn Marino 	}
583*e4b17023SJohn Marino 
584*e4b17023SJohn Marino       else if (code == LO_SUM)
585*e4b17023SJohn Marino 	{
586*e4b17023SJohn Marino           op0 = XEXP (x, 0);
587*e4b17023SJohn Marino           op1 = XEXP (x, 1);
588*e4b17023SJohn Marino 
589*e4b17023SJohn Marino 	  /* The only simplification we do attempts to remove references to op0
590*e4b17023SJohn Marino 	     or make it constant -- in both cases, op0's invalidity will not
591*e4b17023SJohn Marino 	     make the result invalid.  */
592*e4b17023SJohn Marino 	  propagate_rtx_1 (&op0, old_rtx, new_rtx, flags | PR_CAN_APPEAR);
593*e4b17023SJohn Marino 	  valid_ops &= propagate_rtx_1 (&op1, old_rtx, new_rtx, flags);
594*e4b17023SJohn Marino           if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
595*e4b17023SJohn Marino 	    return true;
596*e4b17023SJohn Marino 
597*e4b17023SJohn Marino 	  /* (lo_sum (high x) x) -> x  */
598*e4b17023SJohn Marino 	  if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
599*e4b17023SJohn Marino 	    tem = op1;
600*e4b17023SJohn Marino 	  else
601*e4b17023SJohn Marino 	    tem = gen_rtx_LO_SUM (mode, op0, op1);
602*e4b17023SJohn Marino 
603*e4b17023SJohn Marino 	  /* OP1 is likely not a legitimate address, otherwise there would have
604*e4b17023SJohn Marino 	     been no LO_SUM.  We want it to disappear if it is invalid, return
605*e4b17023SJohn Marino 	     false in that case.  */
606*e4b17023SJohn Marino 	  return memory_address_p (mode, tem);
607*e4b17023SJohn Marino 	}
608*e4b17023SJohn Marino 
609*e4b17023SJohn Marino       else if (code == REG)
610*e4b17023SJohn Marino 	{
611*e4b17023SJohn Marino 	  if (rtx_equal_p (x, old_rtx))
612*e4b17023SJohn Marino 	    {
613*e4b17023SJohn Marino               *px = new_rtx;
614*e4b17023SJohn Marino               return can_appear;
615*e4b17023SJohn Marino 	    }
616*e4b17023SJohn Marino 	}
617*e4b17023SJohn Marino       break;
618*e4b17023SJohn Marino 
619*e4b17023SJohn Marino     default:
620*e4b17023SJohn Marino       break;
621*e4b17023SJohn Marino     }
622*e4b17023SJohn Marino 
623*e4b17023SJohn Marino   /* No change, no trouble.  */
624*e4b17023SJohn Marino   if (tem == NULL_RTX)
625*e4b17023SJohn Marino     return true;
626*e4b17023SJohn Marino 
627*e4b17023SJohn Marino   *px = tem;
628*e4b17023SJohn Marino 
629*e4b17023SJohn Marino   /* The replacement we made so far is valid, if all of the recursive
630*e4b17023SJohn Marino      replacements were valid, or we could simplify everything to
631*e4b17023SJohn Marino      a constant.  */
632*e4b17023SJohn Marino   return valid_ops || can_appear || CONSTANT_P (tem);
633*e4b17023SJohn Marino }
634*e4b17023SJohn Marino 
635*e4b17023SJohn Marino 
636*e4b17023SJohn Marino /* for_each_rtx traversal function that returns 1 if BODY points to
637*e4b17023SJohn Marino    a non-constant mem.  */
638*e4b17023SJohn Marino 
639*e4b17023SJohn Marino static int
varying_mem_p(rtx * body,void * data ATTRIBUTE_UNUSED)640*e4b17023SJohn Marino varying_mem_p (rtx *body, void *data ATTRIBUTE_UNUSED)
641*e4b17023SJohn Marino {
642*e4b17023SJohn Marino   rtx x = *body;
643*e4b17023SJohn Marino   return MEM_P (x) && !MEM_READONLY_P (x);
644*e4b17023SJohn Marino }
645*e4b17023SJohn Marino 
646*e4b17023SJohn Marino 
647*e4b17023SJohn Marino /* Replace all occurrences of OLD in X with NEW and try to simplify the
648*e4b17023SJohn Marino    resulting expression (in mode MODE).  Return a new expression if it is
649*e4b17023SJohn Marino    a constant, otherwise X.
650*e4b17023SJohn Marino 
651*e4b17023SJohn Marino    Simplifications where occurrences of NEW collapse to a constant are always
652*e4b17023SJohn Marino    accepted.  All simplifications are accepted if NEW is a pseudo too.
653*e4b17023SJohn Marino    Otherwise, we accept simplifications that have a lower or equal cost.  */
654*e4b17023SJohn Marino 
655*e4b17023SJohn Marino static rtx
propagate_rtx(rtx x,enum machine_mode mode,rtx old_rtx,rtx new_rtx,bool speed)656*e4b17023SJohn Marino propagate_rtx (rtx x, enum machine_mode mode, rtx old_rtx, rtx new_rtx,
657*e4b17023SJohn Marino 	       bool speed)
658*e4b17023SJohn Marino {
659*e4b17023SJohn Marino   rtx tem;
660*e4b17023SJohn Marino   bool collapsed;
661*e4b17023SJohn Marino   int flags;
662*e4b17023SJohn Marino 
663*e4b17023SJohn Marino   if (REG_P (new_rtx) && REGNO (new_rtx) < FIRST_PSEUDO_REGISTER)
664*e4b17023SJohn Marino     return NULL_RTX;
665*e4b17023SJohn Marino 
666*e4b17023SJohn Marino   flags = 0;
667*e4b17023SJohn Marino   if (REG_P (new_rtx) || CONSTANT_P (new_rtx))
668*e4b17023SJohn Marino     flags |= PR_CAN_APPEAR;
669*e4b17023SJohn Marino   if (!for_each_rtx (&new_rtx, varying_mem_p, NULL))
670*e4b17023SJohn Marino     flags |= PR_HANDLE_MEM;
671*e4b17023SJohn Marino 
672*e4b17023SJohn Marino   if (speed)
673*e4b17023SJohn Marino     flags |= PR_OPTIMIZE_FOR_SPEED;
674*e4b17023SJohn Marino 
675*e4b17023SJohn Marino   tem = x;
676*e4b17023SJohn Marino   collapsed = propagate_rtx_1 (&tem, old_rtx, copy_rtx (new_rtx), flags);
677*e4b17023SJohn Marino   if (tem == x || !collapsed)
678*e4b17023SJohn Marino     return NULL_RTX;
679*e4b17023SJohn Marino 
680*e4b17023SJohn Marino   /* gen_lowpart_common will not be able to process VOIDmode entities other
681*e4b17023SJohn Marino      than CONST_INTs.  */
682*e4b17023SJohn Marino   if (GET_MODE (tem) == VOIDmode && !CONST_INT_P (tem))
683*e4b17023SJohn Marino     return NULL_RTX;
684*e4b17023SJohn Marino 
685*e4b17023SJohn Marino   if (GET_MODE (tem) == VOIDmode)
686*e4b17023SJohn Marino     tem = rtl_hooks.gen_lowpart_no_emit (mode, tem);
687*e4b17023SJohn Marino   else
688*e4b17023SJohn Marino     gcc_assert (GET_MODE (tem) == mode);
689*e4b17023SJohn Marino 
690*e4b17023SJohn Marino   return tem;
691*e4b17023SJohn Marino }
692*e4b17023SJohn Marino 
693*e4b17023SJohn Marino 
694*e4b17023SJohn Marino 
695*e4b17023SJohn Marino 
696*e4b17023SJohn Marino /* Return true if the register from reference REF is killed
697*e4b17023SJohn Marino    between FROM to (but not including) TO.  */
698*e4b17023SJohn Marino 
699*e4b17023SJohn Marino static bool
local_ref_killed_between_p(df_ref ref,rtx from,rtx to)700*e4b17023SJohn Marino local_ref_killed_between_p (df_ref ref, rtx from, rtx to)
701*e4b17023SJohn Marino {
702*e4b17023SJohn Marino   rtx insn;
703*e4b17023SJohn Marino 
704*e4b17023SJohn Marino   for (insn = from; insn != to; insn = NEXT_INSN (insn))
705*e4b17023SJohn Marino     {
706*e4b17023SJohn Marino       df_ref *def_rec;
707*e4b17023SJohn Marino       if (!INSN_P (insn))
708*e4b17023SJohn Marino 	continue;
709*e4b17023SJohn Marino 
710*e4b17023SJohn Marino       for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
711*e4b17023SJohn Marino 	{
712*e4b17023SJohn Marino 	  df_ref def = *def_rec;
713*e4b17023SJohn Marino 	  if (DF_REF_REGNO (ref) == DF_REF_REGNO (def))
714*e4b17023SJohn Marino 	    return true;
715*e4b17023SJohn Marino 	}
716*e4b17023SJohn Marino     }
717*e4b17023SJohn Marino   return false;
718*e4b17023SJohn Marino }
719*e4b17023SJohn Marino 
720*e4b17023SJohn Marino 
721*e4b17023SJohn Marino /* Check if the given DEF is available in INSN.  This would require full
722*e4b17023SJohn Marino    computation of available expressions; we check only restricted conditions:
723*e4b17023SJohn Marino    - if DEF is the sole definition of its register, go ahead;
724*e4b17023SJohn Marino    - in the same basic block, we check for no definitions killing the
725*e4b17023SJohn Marino      definition of DEF_INSN;
726*e4b17023SJohn Marino    - if USE's basic block has DEF's basic block as the sole predecessor,
727*e4b17023SJohn Marino      we check if the definition is killed after DEF_INSN or before
728*e4b17023SJohn Marino      TARGET_INSN insn, in their respective basic blocks.  */
729*e4b17023SJohn Marino static bool
use_killed_between(df_ref use,rtx def_insn,rtx target_insn)730*e4b17023SJohn Marino use_killed_between (df_ref use, rtx def_insn, rtx target_insn)
731*e4b17023SJohn Marino {
732*e4b17023SJohn Marino   basic_block def_bb = BLOCK_FOR_INSN (def_insn);
733*e4b17023SJohn Marino   basic_block target_bb = BLOCK_FOR_INSN (target_insn);
734*e4b17023SJohn Marino   int regno;
735*e4b17023SJohn Marino   df_ref def;
736*e4b17023SJohn Marino 
737*e4b17023SJohn Marino   /* We used to have a def reaching a use that is _before_ the def,
738*e4b17023SJohn Marino      with the def not dominating the use even though the use and def
739*e4b17023SJohn Marino      are in the same basic block, when a register may be used
740*e4b17023SJohn Marino      uninitialized in a loop.  This should not happen anymore since
741*e4b17023SJohn Marino      we do not use reaching definitions, but still we test for such
742*e4b17023SJohn Marino      cases and assume that DEF is not available.  */
743*e4b17023SJohn Marino   if (def_bb == target_bb
744*e4b17023SJohn Marino       ? DF_INSN_LUID (def_insn) >= DF_INSN_LUID (target_insn)
745*e4b17023SJohn Marino       : !dominated_by_p (CDI_DOMINATORS, target_bb, def_bb))
746*e4b17023SJohn Marino     return true;
747*e4b17023SJohn Marino 
748*e4b17023SJohn Marino   /* Check if the reg in USE has only one definition.  We already
749*e4b17023SJohn Marino      know that this definition reaches use, or we wouldn't be here.
750*e4b17023SJohn Marino      However, this is invalid for hard registers because if they are
751*e4b17023SJohn Marino      live at the beginning of the function it does not mean that we
752*e4b17023SJohn Marino      have an uninitialized access.  */
753*e4b17023SJohn Marino   regno = DF_REF_REGNO (use);
754*e4b17023SJohn Marino   def = DF_REG_DEF_CHAIN (regno);
755*e4b17023SJohn Marino   if (def
756*e4b17023SJohn Marino       && DF_REF_NEXT_REG (def) == NULL
757*e4b17023SJohn Marino       && regno >= FIRST_PSEUDO_REGISTER)
758*e4b17023SJohn Marino     return false;
759*e4b17023SJohn Marino 
760*e4b17023SJohn Marino   /* Check locally if we are in the same basic block.  */
761*e4b17023SJohn Marino   if (def_bb == target_bb)
762*e4b17023SJohn Marino     return local_ref_killed_between_p (use, def_insn, target_insn);
763*e4b17023SJohn Marino 
764*e4b17023SJohn Marino   /* Finally, if DEF_BB is the sole predecessor of TARGET_BB.  */
765*e4b17023SJohn Marino   if (single_pred_p (target_bb)
766*e4b17023SJohn Marino       && single_pred (target_bb) == def_bb)
767*e4b17023SJohn Marino     {
768*e4b17023SJohn Marino       df_ref x;
769*e4b17023SJohn Marino 
770*e4b17023SJohn Marino       /* See if USE is killed between DEF_INSN and the last insn in the
771*e4b17023SJohn Marino 	 basic block containing DEF_INSN.  */
772*e4b17023SJohn Marino       x = df_bb_regno_last_def_find (def_bb, regno);
773*e4b17023SJohn Marino       if (x && DF_INSN_LUID (DF_REF_INSN (x)) >= DF_INSN_LUID (def_insn))
774*e4b17023SJohn Marino 	return true;
775*e4b17023SJohn Marino 
776*e4b17023SJohn Marino       /* See if USE is killed between TARGET_INSN and the first insn in the
777*e4b17023SJohn Marino 	 basic block containing TARGET_INSN.  */
778*e4b17023SJohn Marino       x = df_bb_regno_first_def_find (target_bb, regno);
779*e4b17023SJohn Marino       if (x && DF_INSN_LUID (DF_REF_INSN (x)) < DF_INSN_LUID (target_insn))
780*e4b17023SJohn Marino 	return true;
781*e4b17023SJohn Marino 
782*e4b17023SJohn Marino       return false;
783*e4b17023SJohn Marino     }
784*e4b17023SJohn Marino 
785*e4b17023SJohn Marino   /* Otherwise assume the worst case.  */
786*e4b17023SJohn Marino   return true;
787*e4b17023SJohn Marino }
788*e4b17023SJohn Marino 
789*e4b17023SJohn Marino 
790*e4b17023SJohn Marino /* Check if all uses in DEF_INSN can be used in TARGET_INSN.  This
791*e4b17023SJohn Marino    would require full computation of available expressions;
792*e4b17023SJohn Marino    we check only restricted conditions, see use_killed_between.  */
793*e4b17023SJohn Marino static bool
all_uses_available_at(rtx def_insn,rtx target_insn)794*e4b17023SJohn Marino all_uses_available_at (rtx def_insn, rtx target_insn)
795*e4b17023SJohn Marino {
796*e4b17023SJohn Marino   df_ref *use_rec;
797*e4b17023SJohn Marino   struct df_insn_info *insn_info = DF_INSN_INFO_GET (def_insn);
798*e4b17023SJohn Marino   rtx def_set = single_set (def_insn);
799*e4b17023SJohn Marino 
800*e4b17023SJohn Marino   gcc_assert (def_set);
801*e4b17023SJohn Marino 
802*e4b17023SJohn Marino   /* If target_insn comes right after def_insn, which is very common
803*e4b17023SJohn Marino      for addresses, we can use a quicker test.  */
804*e4b17023SJohn Marino   if (NEXT_INSN (def_insn) == target_insn
805*e4b17023SJohn Marino       && REG_P (SET_DEST (def_set)))
806*e4b17023SJohn Marino     {
807*e4b17023SJohn Marino       rtx def_reg = SET_DEST (def_set);
808*e4b17023SJohn Marino 
809*e4b17023SJohn Marino       /* If the insn uses the reg that it defines, the substitution is
810*e4b17023SJohn Marino          invalid.  */
811*e4b17023SJohn Marino       for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++)
812*e4b17023SJohn Marino 	{
813*e4b17023SJohn Marino 	  df_ref use = *use_rec;
814*e4b17023SJohn Marino 	  if (rtx_equal_p (DF_REF_REG (use), def_reg))
815*e4b17023SJohn Marino 	    return false;
816*e4b17023SJohn Marino 	}
817*e4b17023SJohn Marino       for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
818*e4b17023SJohn Marino 	{
819*e4b17023SJohn Marino 	  df_ref use = *use_rec;
820*e4b17023SJohn Marino 	  if (rtx_equal_p (DF_REF_REG (use), def_reg))
821*e4b17023SJohn Marino 	    return false;
822*e4b17023SJohn Marino 	}
823*e4b17023SJohn Marino     }
824*e4b17023SJohn Marino   else
825*e4b17023SJohn Marino     {
826*e4b17023SJohn Marino       rtx def_reg = REG_P (SET_DEST (def_set)) ? SET_DEST (def_set) : NULL_RTX;
827*e4b17023SJohn Marino 
828*e4b17023SJohn Marino       /* Look at all the uses of DEF_INSN, and see if they are not
829*e4b17023SJohn Marino 	 killed between DEF_INSN and TARGET_INSN.  */
830*e4b17023SJohn Marino       for (use_rec = DF_INSN_INFO_USES (insn_info); *use_rec; use_rec++)
831*e4b17023SJohn Marino 	{
832*e4b17023SJohn Marino 	  df_ref use = *use_rec;
833*e4b17023SJohn Marino 	  if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
834*e4b17023SJohn Marino 	    return false;
835*e4b17023SJohn Marino 	  if (use_killed_between (use, def_insn, target_insn))
836*e4b17023SJohn Marino 	    return false;
837*e4b17023SJohn Marino 	}
838*e4b17023SJohn Marino       for (use_rec = DF_INSN_INFO_EQ_USES (insn_info); *use_rec; use_rec++)
839*e4b17023SJohn Marino 	{
840*e4b17023SJohn Marino 	  df_ref use = *use_rec;
841*e4b17023SJohn Marino 	  if (def_reg && rtx_equal_p (DF_REF_REG (use), def_reg))
842*e4b17023SJohn Marino 	    return false;
843*e4b17023SJohn Marino 	  if (use_killed_between (use, def_insn, target_insn))
844*e4b17023SJohn Marino 	    return false;
845*e4b17023SJohn Marino 	}
846*e4b17023SJohn Marino     }
847*e4b17023SJohn Marino 
848*e4b17023SJohn Marino   return true;
849*e4b17023SJohn Marino }
850*e4b17023SJohn Marino 
851*e4b17023SJohn Marino 
852*e4b17023SJohn Marino static df_ref *active_defs;
853*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
854*e4b17023SJohn Marino static sparseset active_defs_check;
855*e4b17023SJohn Marino #endif
856*e4b17023SJohn Marino 
857*e4b17023SJohn Marino /* Fill the ACTIVE_DEFS array with the use->def link for the registers
858*e4b17023SJohn Marino    mentioned in USE_REC.  Register the valid entries in ACTIVE_DEFS_CHECK
859*e4b17023SJohn Marino    too, for checking purposes.  */
860*e4b17023SJohn Marino 
861*e4b17023SJohn Marino static void
register_active_defs(df_ref * use_rec)862*e4b17023SJohn Marino register_active_defs (df_ref *use_rec)
863*e4b17023SJohn Marino {
864*e4b17023SJohn Marino   while (*use_rec)
865*e4b17023SJohn Marino     {
866*e4b17023SJohn Marino       df_ref use = *use_rec++;
867*e4b17023SJohn Marino       df_ref def = get_def_for_use (use);
868*e4b17023SJohn Marino       int regno = DF_REF_REGNO (use);
869*e4b17023SJohn Marino 
870*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
871*e4b17023SJohn Marino       sparseset_set_bit (active_defs_check, regno);
872*e4b17023SJohn Marino #endif
873*e4b17023SJohn Marino       active_defs[regno] = def;
874*e4b17023SJohn Marino     }
875*e4b17023SJohn Marino }
876*e4b17023SJohn Marino 
877*e4b17023SJohn Marino 
878*e4b17023SJohn Marino /* Build the use->def links that we use to update the dataflow info
879*e4b17023SJohn Marino    for new uses.  Note that building the links is very cheap and if
880*e4b17023SJohn Marino    it were done earlier, they could be used to rule out invalid
881*e4b17023SJohn Marino    propagations (in addition to what is done in all_uses_available_at).
882*e4b17023SJohn Marino    I'm not doing this yet, though.  */
883*e4b17023SJohn Marino 
884*e4b17023SJohn Marino static void
update_df_init(rtx def_insn,rtx insn)885*e4b17023SJohn Marino update_df_init (rtx def_insn, rtx insn)
886*e4b17023SJohn Marino {
887*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
888*e4b17023SJohn Marino   sparseset_clear (active_defs_check);
889*e4b17023SJohn Marino #endif
890*e4b17023SJohn Marino   register_active_defs (DF_INSN_USES (def_insn));
891*e4b17023SJohn Marino   register_active_defs (DF_INSN_USES (insn));
892*e4b17023SJohn Marino   register_active_defs (DF_INSN_EQ_USES (insn));
893*e4b17023SJohn Marino }
894*e4b17023SJohn Marino 
895*e4b17023SJohn Marino 
896*e4b17023SJohn Marino /* Update the USE_DEF_REF array for the given use, using the active definitions
897*e4b17023SJohn Marino    in the ACTIVE_DEFS array to match pseudos to their def. */
898*e4b17023SJohn Marino 
899*e4b17023SJohn Marino static inline void
update_uses(df_ref * use_rec)900*e4b17023SJohn Marino update_uses (df_ref *use_rec)
901*e4b17023SJohn Marino {
902*e4b17023SJohn Marino   while (*use_rec)
903*e4b17023SJohn Marino     {
904*e4b17023SJohn Marino       df_ref use = *use_rec++;
905*e4b17023SJohn Marino       int regno = DF_REF_REGNO (use);
906*e4b17023SJohn Marino 
907*e4b17023SJohn Marino       /* Set up the use-def chain.  */
908*e4b17023SJohn Marino       if (DF_REF_ID (use) >= (int) VEC_length (df_ref, use_def_ref))
909*e4b17023SJohn Marino         VEC_safe_grow_cleared (df_ref, heap, use_def_ref,
910*e4b17023SJohn Marino                                DF_REF_ID (use) + 1);
911*e4b17023SJohn Marino 
912*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
913*e4b17023SJohn Marino       gcc_assert (sparseset_bit_p (active_defs_check, regno));
914*e4b17023SJohn Marino #endif
915*e4b17023SJohn Marino       VEC_replace (df_ref, use_def_ref, DF_REF_ID (use), active_defs[regno]);
916*e4b17023SJohn Marino     }
917*e4b17023SJohn Marino }
918*e4b17023SJohn Marino 
919*e4b17023SJohn Marino 
920*e4b17023SJohn Marino /* Update the USE_DEF_REF array for the uses in INSN.  Only update note
921*e4b17023SJohn Marino    uses if NOTES_ONLY is true.  */
922*e4b17023SJohn Marino 
923*e4b17023SJohn Marino static void
update_df(rtx insn,rtx note)924*e4b17023SJohn Marino update_df (rtx insn, rtx note)
925*e4b17023SJohn Marino {
926*e4b17023SJohn Marino   struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
927*e4b17023SJohn Marino 
928*e4b17023SJohn Marino   if (note)
929*e4b17023SJohn Marino     {
930*e4b17023SJohn Marino       df_uses_create (&XEXP (note, 0), insn, DF_REF_IN_NOTE);
931*e4b17023SJohn Marino       df_notes_rescan (insn);
932*e4b17023SJohn Marino     }
933*e4b17023SJohn Marino   else
934*e4b17023SJohn Marino     {
935*e4b17023SJohn Marino       df_uses_create (&PATTERN (insn), insn, 0);
936*e4b17023SJohn Marino       df_insn_rescan (insn);
937*e4b17023SJohn Marino       update_uses (DF_INSN_INFO_USES (insn_info));
938*e4b17023SJohn Marino     }
939*e4b17023SJohn Marino 
940*e4b17023SJohn Marino   update_uses (DF_INSN_INFO_EQ_USES (insn_info));
941*e4b17023SJohn Marino }
942*e4b17023SJohn Marino 
943*e4b17023SJohn Marino 
944*e4b17023SJohn Marino /* Try substituting NEW into LOC, which originated from forward propagation
945*e4b17023SJohn Marino    of USE's value from DEF_INSN.  SET_REG_EQUAL says whether we are
946*e4b17023SJohn Marino    substituting the whole SET_SRC, so we can set a REG_EQUAL note if the
947*e4b17023SJohn Marino    new insn is not recognized.  Return whether the substitution was
948*e4b17023SJohn Marino    performed.  */
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino static bool
try_fwprop_subst(df_ref use,rtx * loc,rtx new_rtx,rtx def_insn,bool set_reg_equal)951*e4b17023SJohn Marino try_fwprop_subst (df_ref use, rtx *loc, rtx new_rtx, rtx def_insn, bool set_reg_equal)
952*e4b17023SJohn Marino {
953*e4b17023SJohn Marino   rtx insn = DF_REF_INSN (use);
954*e4b17023SJohn Marino   rtx set = single_set (insn);
955*e4b17023SJohn Marino   rtx note = NULL_RTX;
956*e4b17023SJohn Marino   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
957*e4b17023SJohn Marino   int old_cost = 0;
958*e4b17023SJohn Marino   bool ok;
959*e4b17023SJohn Marino 
960*e4b17023SJohn Marino   update_df_init (def_insn, insn);
961*e4b17023SJohn Marino 
962*e4b17023SJohn Marino   /* forward_propagate_subreg may be operating on an instruction with
963*e4b17023SJohn Marino      multiple sets.  If so, assume the cost of the new instruction is
964*e4b17023SJohn Marino      not greater than the old one.  */
965*e4b17023SJohn Marino   if (set)
966*e4b17023SJohn Marino     old_cost = set_src_cost (SET_SRC (set), speed);
967*e4b17023SJohn Marino   if (dump_file)
968*e4b17023SJohn Marino     {
969*e4b17023SJohn Marino       fprintf (dump_file, "\nIn insn %d, replacing\n ", INSN_UID (insn));
970*e4b17023SJohn Marino       print_inline_rtx (dump_file, *loc, 2);
971*e4b17023SJohn Marino       fprintf (dump_file, "\n with ");
972*e4b17023SJohn Marino       print_inline_rtx (dump_file, new_rtx, 2);
973*e4b17023SJohn Marino       fprintf (dump_file, "\n");
974*e4b17023SJohn Marino     }
975*e4b17023SJohn Marino 
976*e4b17023SJohn Marino   validate_unshare_change (insn, loc, new_rtx, true);
977*e4b17023SJohn Marino   if (!verify_changes (0))
978*e4b17023SJohn Marino     {
979*e4b17023SJohn Marino       if (dump_file)
980*e4b17023SJohn Marino 	fprintf (dump_file, "Changes to insn %d not recognized\n",
981*e4b17023SJohn Marino 		 INSN_UID (insn));
982*e4b17023SJohn Marino       ok = false;
983*e4b17023SJohn Marino     }
984*e4b17023SJohn Marino 
985*e4b17023SJohn Marino   else if (DF_REF_TYPE (use) == DF_REF_REG_USE
986*e4b17023SJohn Marino 	   && set
987*e4b17023SJohn Marino 	   && set_src_cost (SET_SRC (set), speed) > old_cost)
988*e4b17023SJohn Marino     {
989*e4b17023SJohn Marino       if (dump_file)
990*e4b17023SJohn Marino 	fprintf (dump_file, "Changes to insn %d not profitable\n",
991*e4b17023SJohn Marino 		 INSN_UID (insn));
992*e4b17023SJohn Marino       ok = false;
993*e4b17023SJohn Marino     }
994*e4b17023SJohn Marino 
995*e4b17023SJohn Marino   else
996*e4b17023SJohn Marino     {
997*e4b17023SJohn Marino       if (dump_file)
998*e4b17023SJohn Marino 	fprintf (dump_file, "Changed insn %d\n", INSN_UID (insn));
999*e4b17023SJohn Marino       ok = true;
1000*e4b17023SJohn Marino     }
1001*e4b17023SJohn Marino 
1002*e4b17023SJohn Marino   if (ok)
1003*e4b17023SJohn Marino     {
1004*e4b17023SJohn Marino       confirm_change_group ();
1005*e4b17023SJohn Marino       num_changes++;
1006*e4b17023SJohn Marino     }
1007*e4b17023SJohn Marino   else
1008*e4b17023SJohn Marino     {
1009*e4b17023SJohn Marino       cancel_changes (0);
1010*e4b17023SJohn Marino 
1011*e4b17023SJohn Marino       /* Can also record a simplified value in a REG_EQUAL note,
1012*e4b17023SJohn Marino 	 making a new one if one does not already exist.  */
1013*e4b17023SJohn Marino       if (set_reg_equal)
1014*e4b17023SJohn Marino 	{
1015*e4b17023SJohn Marino 	  if (dump_file)
1016*e4b17023SJohn Marino 	    fprintf (dump_file, " Setting REG_EQUAL note\n");
1017*e4b17023SJohn Marino 
1018*e4b17023SJohn Marino 	  note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (new_rtx));
1019*e4b17023SJohn Marino 	}
1020*e4b17023SJohn Marino     }
1021*e4b17023SJohn Marino 
1022*e4b17023SJohn Marino   if ((ok || note) && !CONSTANT_P (new_rtx))
1023*e4b17023SJohn Marino     update_df (insn, note);
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino   return ok;
1026*e4b17023SJohn Marino }
1027*e4b17023SJohn Marino 
1028*e4b17023SJohn Marino /* For the given single_set INSN, containing SRC known to be a
1029*e4b17023SJohn Marino    ZERO_EXTEND or SIGN_EXTEND of a register, return true if INSN
1030*e4b17023SJohn Marino    is redundant due to the register being set by a LOAD_EXTEND_OP
1031*e4b17023SJohn Marino    load from memory.  */
1032*e4b17023SJohn Marino 
1033*e4b17023SJohn Marino static bool
free_load_extend(rtx src,rtx insn)1034*e4b17023SJohn Marino free_load_extend (rtx src, rtx insn)
1035*e4b17023SJohn Marino {
1036*e4b17023SJohn Marino   rtx reg;
1037*e4b17023SJohn Marino   df_ref *use_vec;
1038*e4b17023SJohn Marino   df_ref use = 0, def;
1039*e4b17023SJohn Marino 
1040*e4b17023SJohn Marino   reg = XEXP (src, 0);
1041*e4b17023SJohn Marino #ifdef LOAD_EXTEND_OP
1042*e4b17023SJohn Marino   if (LOAD_EXTEND_OP (GET_MODE (reg)) != GET_CODE (src))
1043*e4b17023SJohn Marino #endif
1044*e4b17023SJohn Marino     return false;
1045*e4b17023SJohn Marino 
1046*e4b17023SJohn Marino   for (use_vec = DF_INSN_USES (insn); *use_vec; use_vec++)
1047*e4b17023SJohn Marino     {
1048*e4b17023SJohn Marino       use = *use_vec;
1049*e4b17023SJohn Marino 
1050*e4b17023SJohn Marino       if (!DF_REF_IS_ARTIFICIAL (use)
1051*e4b17023SJohn Marino 	  && DF_REF_TYPE (use) == DF_REF_REG_USE
1052*e4b17023SJohn Marino 	  && DF_REF_REG (use) == reg)
1053*e4b17023SJohn Marino 	break;
1054*e4b17023SJohn Marino     }
1055*e4b17023SJohn Marino   if (!use)
1056*e4b17023SJohn Marino     return false;
1057*e4b17023SJohn Marino 
1058*e4b17023SJohn Marino   def = get_def_for_use (use);
1059*e4b17023SJohn Marino   if (!def)
1060*e4b17023SJohn Marino     return false;
1061*e4b17023SJohn Marino 
1062*e4b17023SJohn Marino   if (DF_REF_IS_ARTIFICIAL (def))
1063*e4b17023SJohn Marino     return false;
1064*e4b17023SJohn Marino 
1065*e4b17023SJohn Marino   if (NONJUMP_INSN_P (DF_REF_INSN (def)))
1066*e4b17023SJohn Marino     {
1067*e4b17023SJohn Marino       rtx patt = PATTERN (DF_REF_INSN (def));
1068*e4b17023SJohn Marino 
1069*e4b17023SJohn Marino       if (GET_CODE (patt) == SET
1070*e4b17023SJohn Marino 	  && GET_CODE (SET_SRC (patt)) == MEM
1071*e4b17023SJohn Marino 	  && rtx_equal_p (SET_DEST (patt), reg))
1072*e4b17023SJohn Marino 	return true;
1073*e4b17023SJohn Marino     }
1074*e4b17023SJohn Marino   return false;
1075*e4b17023SJohn Marino }
1076*e4b17023SJohn Marino 
1077*e4b17023SJohn Marino /* If USE is a subreg, see if it can be replaced by a pseudo.  */
1078*e4b17023SJohn Marino 
1079*e4b17023SJohn Marino static bool
forward_propagate_subreg(df_ref use,rtx def_insn,rtx def_set)1080*e4b17023SJohn Marino forward_propagate_subreg (df_ref use, rtx def_insn, rtx def_set)
1081*e4b17023SJohn Marino {
1082*e4b17023SJohn Marino   rtx use_reg = DF_REF_REG (use);
1083*e4b17023SJohn Marino   rtx use_insn, src;
1084*e4b17023SJohn Marino 
1085*e4b17023SJohn Marino   /* Only consider subregs... */
1086*e4b17023SJohn Marino   enum machine_mode use_mode = GET_MODE (use_reg);
1087*e4b17023SJohn Marino   if (GET_CODE (use_reg) != SUBREG
1088*e4b17023SJohn Marino       || !REG_P (SET_DEST (def_set)))
1089*e4b17023SJohn Marino     return false;
1090*e4b17023SJohn Marino 
1091*e4b17023SJohn Marino   /* If this is a paradoxical SUBREG...  */
1092*e4b17023SJohn Marino   if (GET_MODE_SIZE (use_mode)
1093*e4b17023SJohn Marino       > GET_MODE_SIZE (GET_MODE (SUBREG_REG (use_reg))))
1094*e4b17023SJohn Marino     {
1095*e4b17023SJohn Marino       /* If this is a paradoxical SUBREG, we have no idea what value the
1096*e4b17023SJohn Marino 	 extra bits would have.  However, if the operand is equivalent to
1097*e4b17023SJohn Marino 	 a SUBREG whose operand is the same as our mode, and all the modes
1098*e4b17023SJohn Marino 	 are within a word, we can just use the inner operand because
1099*e4b17023SJohn Marino 	 these SUBREGs just say how to treat the register.  */
1100*e4b17023SJohn Marino       use_insn = DF_REF_INSN (use);
1101*e4b17023SJohn Marino       src = SET_SRC (def_set);
1102*e4b17023SJohn Marino       if (GET_CODE (src) == SUBREG
1103*e4b17023SJohn Marino 	  && REG_P (SUBREG_REG (src))
1104*e4b17023SJohn Marino 	  && REGNO (SUBREG_REG (src)) >= FIRST_PSEUDO_REGISTER
1105*e4b17023SJohn Marino 	  && GET_MODE (SUBREG_REG (src)) == use_mode
1106*e4b17023SJohn Marino 	  && subreg_lowpart_p (src)
1107*e4b17023SJohn Marino 	  && all_uses_available_at (def_insn, use_insn))
1108*e4b17023SJohn Marino 	return try_fwprop_subst (use, DF_REF_LOC (use), SUBREG_REG (src),
1109*e4b17023SJohn Marino 				 def_insn, false);
1110*e4b17023SJohn Marino     }
1111*e4b17023SJohn Marino 
1112*e4b17023SJohn Marino   /* If this is a SUBREG of a ZERO_EXTEND or SIGN_EXTEND, and the SUBREG
1113*e4b17023SJohn Marino      is the low part of the reg being extended then just use the inner
1114*e4b17023SJohn Marino      operand.  Don't do this if the ZERO_EXTEND or SIGN_EXTEND insn will
1115*e4b17023SJohn Marino      be removed due to it matching a LOAD_EXTEND_OP load from memory,
1116*e4b17023SJohn Marino      or due to the operation being a no-op when applied to registers.
1117*e4b17023SJohn Marino      For example, if we have:
1118*e4b17023SJohn Marino 
1119*e4b17023SJohn Marino 	 A: (set (reg:DI X) (sign_extend:DI (reg:SI Y)))
1120*e4b17023SJohn Marino 	 B: (... (subreg:SI (reg:DI X)) ...)
1121*e4b17023SJohn Marino 
1122*e4b17023SJohn Marino      and mode_rep_extended says that Y is already sign-extended,
1123*e4b17023SJohn Marino      the backend will typically allow A to be combined with the
1124*e4b17023SJohn Marino      definition of Y or, failing that, allow A to be deleted after
1125*e4b17023SJohn Marino      reload through register tying.  Introducing more uses of Y
1126*e4b17023SJohn Marino      prevents both optimisations.  */
1127*e4b17023SJohn Marino   else if (subreg_lowpart_p (use_reg))
1128*e4b17023SJohn Marino     {
1129*e4b17023SJohn Marino       use_insn = DF_REF_INSN (use);
1130*e4b17023SJohn Marino       src = SET_SRC (def_set);
1131*e4b17023SJohn Marino       if ((GET_CODE (src) == ZERO_EXTEND
1132*e4b17023SJohn Marino 	   || GET_CODE (src) == SIGN_EXTEND)
1133*e4b17023SJohn Marino 	  && REG_P (XEXP (src, 0))
1134*e4b17023SJohn Marino 	  && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
1135*e4b17023SJohn Marino 	  && GET_MODE (XEXP (src, 0)) == use_mode
1136*e4b17023SJohn Marino 	  && !free_load_extend (src, def_insn)
1137*e4b17023SJohn Marino 	  && (targetm.mode_rep_extended (use_mode, GET_MODE (src))
1138*e4b17023SJohn Marino 	      != (int) GET_CODE (src))
1139*e4b17023SJohn Marino 	  && all_uses_available_at (def_insn, use_insn))
1140*e4b17023SJohn Marino 	return try_fwprop_subst (use, DF_REF_LOC (use), XEXP (src, 0),
1141*e4b17023SJohn Marino 				 def_insn, false);
1142*e4b17023SJohn Marino     }
1143*e4b17023SJohn Marino 
1144*e4b17023SJohn Marino   return false;
1145*e4b17023SJohn Marino }
1146*e4b17023SJohn Marino 
1147*e4b17023SJohn Marino /* Try to replace USE with SRC (defined in DEF_INSN) in __asm.  */
1148*e4b17023SJohn Marino 
1149*e4b17023SJohn Marino static bool
forward_propagate_asm(df_ref use,rtx def_insn,rtx def_set,rtx reg)1150*e4b17023SJohn Marino forward_propagate_asm (df_ref use, rtx def_insn, rtx def_set, rtx reg)
1151*e4b17023SJohn Marino {
1152*e4b17023SJohn Marino   rtx use_insn = DF_REF_INSN (use), src, use_pat, asm_operands, new_rtx, *loc;
1153*e4b17023SJohn Marino   int speed_p, i;
1154*e4b17023SJohn Marino   df_ref *use_vec;
1155*e4b17023SJohn Marino 
1156*e4b17023SJohn Marino   gcc_assert ((DF_REF_FLAGS (use) & DF_REF_IN_NOTE) == 0);
1157*e4b17023SJohn Marino 
1158*e4b17023SJohn Marino   src = SET_SRC (def_set);
1159*e4b17023SJohn Marino   use_pat = PATTERN (use_insn);
1160*e4b17023SJohn Marino 
1161*e4b17023SJohn Marino   /* In __asm don't replace if src might need more registers than
1162*e4b17023SJohn Marino      reg, as that could increase register pressure on the __asm.  */
1163*e4b17023SJohn Marino   use_vec = DF_INSN_USES (def_insn);
1164*e4b17023SJohn Marino   if (use_vec[0] && use_vec[1])
1165*e4b17023SJohn Marino     return false;
1166*e4b17023SJohn Marino 
1167*e4b17023SJohn Marino   update_df_init (def_insn, use_insn);
1168*e4b17023SJohn Marino   speed_p = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
1169*e4b17023SJohn Marino   asm_operands = NULL_RTX;
1170*e4b17023SJohn Marino   switch (GET_CODE (use_pat))
1171*e4b17023SJohn Marino     {
1172*e4b17023SJohn Marino     case ASM_OPERANDS:
1173*e4b17023SJohn Marino       asm_operands = use_pat;
1174*e4b17023SJohn Marino       break;
1175*e4b17023SJohn Marino     case SET:
1176*e4b17023SJohn Marino       if (MEM_P (SET_DEST (use_pat)))
1177*e4b17023SJohn Marino 	{
1178*e4b17023SJohn Marino 	  loc = &SET_DEST (use_pat);
1179*e4b17023SJohn Marino 	  new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
1180*e4b17023SJohn Marino 	  if (new_rtx)
1181*e4b17023SJohn Marino 	    validate_unshare_change (use_insn, loc, new_rtx, true);
1182*e4b17023SJohn Marino 	}
1183*e4b17023SJohn Marino       asm_operands = SET_SRC (use_pat);
1184*e4b17023SJohn Marino       break;
1185*e4b17023SJohn Marino     case PARALLEL:
1186*e4b17023SJohn Marino       for (i = 0; i < XVECLEN (use_pat, 0); i++)
1187*e4b17023SJohn Marino 	if (GET_CODE (XVECEXP (use_pat, 0, i)) == SET)
1188*e4b17023SJohn Marino 	  {
1189*e4b17023SJohn Marino 	    if (MEM_P (SET_DEST (XVECEXP (use_pat, 0, i))))
1190*e4b17023SJohn Marino 	      {
1191*e4b17023SJohn Marino 		loc = &SET_DEST (XVECEXP (use_pat, 0, i));
1192*e4b17023SJohn Marino 		new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg,
1193*e4b17023SJohn Marino 					 src, speed_p);
1194*e4b17023SJohn Marino 		if (new_rtx)
1195*e4b17023SJohn Marino 		  validate_unshare_change (use_insn, loc, new_rtx, true);
1196*e4b17023SJohn Marino 	      }
1197*e4b17023SJohn Marino 	    asm_operands = SET_SRC (XVECEXP (use_pat, 0, i));
1198*e4b17023SJohn Marino 	  }
1199*e4b17023SJohn Marino 	else if (GET_CODE (XVECEXP (use_pat, 0, i)) == ASM_OPERANDS)
1200*e4b17023SJohn Marino 	  asm_operands = XVECEXP (use_pat, 0, i);
1201*e4b17023SJohn Marino       break;
1202*e4b17023SJohn Marino     default:
1203*e4b17023SJohn Marino       gcc_unreachable ();
1204*e4b17023SJohn Marino     }
1205*e4b17023SJohn Marino 
1206*e4b17023SJohn Marino   gcc_assert (asm_operands && GET_CODE (asm_operands) == ASM_OPERANDS);
1207*e4b17023SJohn Marino   for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (asm_operands); i++)
1208*e4b17023SJohn Marino     {
1209*e4b17023SJohn Marino       loc = &ASM_OPERANDS_INPUT (asm_operands, i);
1210*e4b17023SJohn Marino       new_rtx = propagate_rtx (*loc, GET_MODE (*loc), reg, src, speed_p);
1211*e4b17023SJohn Marino       if (new_rtx)
1212*e4b17023SJohn Marino 	validate_unshare_change (use_insn, loc, new_rtx, true);
1213*e4b17023SJohn Marino     }
1214*e4b17023SJohn Marino 
1215*e4b17023SJohn Marino   if (num_changes_pending () == 0 || !apply_change_group ())
1216*e4b17023SJohn Marino     return false;
1217*e4b17023SJohn Marino 
1218*e4b17023SJohn Marino   update_df (use_insn, NULL);
1219*e4b17023SJohn Marino   num_changes++;
1220*e4b17023SJohn Marino   return true;
1221*e4b17023SJohn Marino }
1222*e4b17023SJohn Marino 
1223*e4b17023SJohn Marino /* Try to replace USE with SRC (defined in DEF_INSN) and simplify the
1224*e4b17023SJohn Marino    result.  */
1225*e4b17023SJohn Marino 
1226*e4b17023SJohn Marino static bool
forward_propagate_and_simplify(df_ref use,rtx def_insn,rtx def_set)1227*e4b17023SJohn Marino forward_propagate_and_simplify (df_ref use, rtx def_insn, rtx def_set)
1228*e4b17023SJohn Marino {
1229*e4b17023SJohn Marino   rtx use_insn = DF_REF_INSN (use);
1230*e4b17023SJohn Marino   rtx use_set = single_set (use_insn);
1231*e4b17023SJohn Marino   rtx src, reg, new_rtx, *loc;
1232*e4b17023SJohn Marino   bool set_reg_equal;
1233*e4b17023SJohn Marino   enum machine_mode mode;
1234*e4b17023SJohn Marino   int asm_use = -1;
1235*e4b17023SJohn Marino 
1236*e4b17023SJohn Marino   if (INSN_CODE (use_insn) < 0)
1237*e4b17023SJohn Marino     asm_use = asm_noperands (PATTERN (use_insn));
1238*e4b17023SJohn Marino 
1239*e4b17023SJohn Marino   if (!use_set && asm_use < 0 && !DEBUG_INSN_P (use_insn))
1240*e4b17023SJohn Marino     return false;
1241*e4b17023SJohn Marino 
1242*e4b17023SJohn Marino   /* Do not propagate into PC, CC0, etc.  */
1243*e4b17023SJohn Marino   if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode)
1244*e4b17023SJohn Marino     return false;
1245*e4b17023SJohn Marino 
1246*e4b17023SJohn Marino   /* If def and use are subreg, check if they match.  */
1247*e4b17023SJohn Marino   reg = DF_REF_REG (use);
1248*e4b17023SJohn Marino   if (GET_CODE (reg) == SUBREG && GET_CODE (SET_DEST (def_set)) == SUBREG)
1249*e4b17023SJohn Marino     {
1250*e4b17023SJohn Marino       if (SUBREG_BYTE (SET_DEST (def_set)) != SUBREG_BYTE (reg))
1251*e4b17023SJohn Marino 	return false;
1252*e4b17023SJohn Marino     }
1253*e4b17023SJohn Marino   /* Check if the def had a subreg, but the use has the whole reg.  */
1254*e4b17023SJohn Marino   else if (REG_P (reg) && GET_CODE (SET_DEST (def_set)) == SUBREG)
1255*e4b17023SJohn Marino     return false;
1256*e4b17023SJohn Marino   /* Check if the use has a subreg, but the def had the whole reg.  Unlike the
1257*e4b17023SJohn Marino      previous case, the optimization is possible and often useful indeed.  */
1258*e4b17023SJohn Marino   else if (GET_CODE (reg) == SUBREG && REG_P (SET_DEST (def_set)))
1259*e4b17023SJohn Marino     reg = SUBREG_REG (reg);
1260*e4b17023SJohn Marino 
1261*e4b17023SJohn Marino   /* Make sure that we can treat REG as having the same mode as the
1262*e4b17023SJohn Marino      source of DEF_SET.  */
1263*e4b17023SJohn Marino   if (GET_MODE (SET_DEST (def_set)) != GET_MODE (reg))
1264*e4b17023SJohn Marino     return false;
1265*e4b17023SJohn Marino 
1266*e4b17023SJohn Marino   /* Check if the substitution is valid (last, because it's the most
1267*e4b17023SJohn Marino      expensive check!).  */
1268*e4b17023SJohn Marino   src = SET_SRC (def_set);
1269*e4b17023SJohn Marino   if (!CONSTANT_P (src) && !all_uses_available_at (def_insn, use_insn))
1270*e4b17023SJohn Marino     return false;
1271*e4b17023SJohn Marino 
1272*e4b17023SJohn Marino   /* Check if the def is loading something from the constant pool; in this
1273*e4b17023SJohn Marino      case we would undo optimization such as compress_float_constant.
1274*e4b17023SJohn Marino      Still, we can set a REG_EQUAL note.  */
1275*e4b17023SJohn Marino   if (MEM_P (src) && MEM_READONLY_P (src))
1276*e4b17023SJohn Marino     {
1277*e4b17023SJohn Marino       rtx x = avoid_constant_pool_reference (src);
1278*e4b17023SJohn Marino       if (x != src && use_set)
1279*e4b17023SJohn Marino 	{
1280*e4b17023SJohn Marino           rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
1281*e4b17023SJohn Marino 	  rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (use_set);
1282*e4b17023SJohn Marino 	  rtx new_rtx = simplify_replace_rtx (old_rtx, src, x);
1283*e4b17023SJohn Marino 	  if (old_rtx != new_rtx)
1284*e4b17023SJohn Marino             set_unique_reg_note (use_insn, REG_EQUAL, copy_rtx (new_rtx));
1285*e4b17023SJohn Marino 	}
1286*e4b17023SJohn Marino       return false;
1287*e4b17023SJohn Marino     }
1288*e4b17023SJohn Marino 
1289*e4b17023SJohn Marino   if (asm_use >= 0)
1290*e4b17023SJohn Marino     return forward_propagate_asm (use, def_insn, def_set, reg);
1291*e4b17023SJohn Marino 
1292*e4b17023SJohn Marino   /* Else try simplifying.  */
1293*e4b17023SJohn Marino 
1294*e4b17023SJohn Marino   if (DF_REF_TYPE (use) == DF_REF_REG_MEM_STORE)
1295*e4b17023SJohn Marino     {
1296*e4b17023SJohn Marino       loc = &SET_DEST (use_set);
1297*e4b17023SJohn Marino       set_reg_equal = false;
1298*e4b17023SJohn Marino     }
1299*e4b17023SJohn Marino   else if (!use_set)
1300*e4b17023SJohn Marino     {
1301*e4b17023SJohn Marino       loc = &INSN_VAR_LOCATION_LOC (use_insn);
1302*e4b17023SJohn Marino       set_reg_equal = false;
1303*e4b17023SJohn Marino     }
1304*e4b17023SJohn Marino   else
1305*e4b17023SJohn Marino     {
1306*e4b17023SJohn Marino       rtx note = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
1307*e4b17023SJohn Marino       if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
1308*e4b17023SJohn Marino 	loc = &XEXP (note, 0);
1309*e4b17023SJohn Marino       else
1310*e4b17023SJohn Marino 	loc = &SET_SRC (use_set);
1311*e4b17023SJohn Marino 
1312*e4b17023SJohn Marino       /* Do not replace an existing REG_EQUAL note if the insn is not
1313*e4b17023SJohn Marino 	 recognized.  Either we're already replacing in the note, or we'll
1314*e4b17023SJohn Marino 	 separately try plugging the definition in the note and simplifying.
1315*e4b17023SJohn Marino 	 And only install a REQ_EQUAL note when the destination is a REG,
1316*e4b17023SJohn Marino 	 as the note would be invalid otherwise.  */
1317*e4b17023SJohn Marino       set_reg_equal = (note == NULL_RTX && REG_P (SET_DEST (use_set)));
1318*e4b17023SJohn Marino     }
1319*e4b17023SJohn Marino 
1320*e4b17023SJohn Marino   if (GET_MODE (*loc) == VOIDmode)
1321*e4b17023SJohn Marino     mode = GET_MODE (SET_DEST (use_set));
1322*e4b17023SJohn Marino   else
1323*e4b17023SJohn Marino     mode = GET_MODE (*loc);
1324*e4b17023SJohn Marino 
1325*e4b17023SJohn Marino   new_rtx = propagate_rtx (*loc, mode, reg, src,
1326*e4b17023SJohn Marino   			   optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn)));
1327*e4b17023SJohn Marino 
1328*e4b17023SJohn Marino   if (!new_rtx)
1329*e4b17023SJohn Marino     return false;
1330*e4b17023SJohn Marino 
1331*e4b17023SJohn Marino   return try_fwprop_subst (use, loc, new_rtx, def_insn, set_reg_equal);
1332*e4b17023SJohn Marino }
1333*e4b17023SJohn Marino 
1334*e4b17023SJohn Marino 
1335*e4b17023SJohn Marino /* Given a use USE of an insn, if it has a single reaching
1336*e4b17023SJohn Marino    definition, try to forward propagate it into that insn.
1337*e4b17023SJohn Marino    Return true if cfg cleanup will be needed.  */
1338*e4b17023SJohn Marino 
1339*e4b17023SJohn Marino static bool
forward_propagate_into(df_ref use)1340*e4b17023SJohn Marino forward_propagate_into (df_ref use)
1341*e4b17023SJohn Marino {
1342*e4b17023SJohn Marino   df_ref def;
1343*e4b17023SJohn Marino   rtx def_insn, def_set, use_insn;
1344*e4b17023SJohn Marino   rtx parent;
1345*e4b17023SJohn Marino 
1346*e4b17023SJohn Marino   if (DF_REF_FLAGS (use) & DF_REF_READ_WRITE)
1347*e4b17023SJohn Marino     return false;
1348*e4b17023SJohn Marino   if (DF_REF_IS_ARTIFICIAL (use))
1349*e4b17023SJohn Marino     return false;
1350*e4b17023SJohn Marino 
1351*e4b17023SJohn Marino   /* Only consider uses that have a single definition.  */
1352*e4b17023SJohn Marino   def = get_def_for_use (use);
1353*e4b17023SJohn Marino   if (!def)
1354*e4b17023SJohn Marino     return false;
1355*e4b17023SJohn Marino   if (DF_REF_FLAGS (def) & DF_REF_READ_WRITE)
1356*e4b17023SJohn Marino     return false;
1357*e4b17023SJohn Marino   if (DF_REF_IS_ARTIFICIAL (def))
1358*e4b17023SJohn Marino     return false;
1359*e4b17023SJohn Marino 
1360*e4b17023SJohn Marino   /* Do not propagate loop invariant definitions inside the loop.  */
1361*e4b17023SJohn Marino   if (DF_REF_BB (def)->loop_father != DF_REF_BB (use)->loop_father)
1362*e4b17023SJohn Marino     return false;
1363*e4b17023SJohn Marino 
1364*e4b17023SJohn Marino   /* Check if the use is still present in the insn!  */
1365*e4b17023SJohn Marino   use_insn = DF_REF_INSN (use);
1366*e4b17023SJohn Marino   if (DF_REF_FLAGS (use) & DF_REF_IN_NOTE)
1367*e4b17023SJohn Marino     parent = find_reg_note (use_insn, REG_EQUAL, NULL_RTX);
1368*e4b17023SJohn Marino   else
1369*e4b17023SJohn Marino     parent = PATTERN (use_insn);
1370*e4b17023SJohn Marino 
1371*e4b17023SJohn Marino   if (!reg_mentioned_p (DF_REF_REG (use), parent))
1372*e4b17023SJohn Marino     return false;
1373*e4b17023SJohn Marino 
1374*e4b17023SJohn Marino   def_insn = DF_REF_INSN (def);
1375*e4b17023SJohn Marino   if (multiple_sets (def_insn))
1376*e4b17023SJohn Marino     return false;
1377*e4b17023SJohn Marino   def_set = single_set (def_insn);
1378*e4b17023SJohn Marino   if (!def_set)
1379*e4b17023SJohn Marino     return false;
1380*e4b17023SJohn Marino 
1381*e4b17023SJohn Marino   /* Only try one kind of propagation.  If two are possible, we'll
1382*e4b17023SJohn Marino      do it on the following iterations.  */
1383*e4b17023SJohn Marino   if (forward_propagate_and_simplify (use, def_insn, def_set)
1384*e4b17023SJohn Marino       || forward_propagate_subreg (use, def_insn, def_set))
1385*e4b17023SJohn Marino     {
1386*e4b17023SJohn Marino       if (cfun->can_throw_non_call_exceptions
1387*e4b17023SJohn Marino 	  && find_reg_note (use_insn, REG_EH_REGION, NULL_RTX)
1388*e4b17023SJohn Marino 	  && purge_dead_edges (DF_REF_BB (use)))
1389*e4b17023SJohn Marino 	return true;
1390*e4b17023SJohn Marino     }
1391*e4b17023SJohn Marino   return false;
1392*e4b17023SJohn Marino }
1393*e4b17023SJohn Marino 
1394*e4b17023SJohn Marino 
1395*e4b17023SJohn Marino static void
fwprop_init(void)1396*e4b17023SJohn Marino fwprop_init (void)
1397*e4b17023SJohn Marino {
1398*e4b17023SJohn Marino   num_changes = 0;
1399*e4b17023SJohn Marino   calculate_dominance_info (CDI_DOMINATORS);
1400*e4b17023SJohn Marino 
1401*e4b17023SJohn Marino   /* We do not always want to propagate into loops, so we have to find
1402*e4b17023SJohn Marino      loops and be careful about them.  But we have to call flow_loops_find
1403*e4b17023SJohn Marino      before df_analyze, because flow_loops_find may introduce new jump
1404*e4b17023SJohn Marino      insns (sadly) if we are not working in cfglayout mode.  */
1405*e4b17023SJohn Marino   loop_optimizer_init (0);
1406*e4b17023SJohn Marino 
1407*e4b17023SJohn Marino   build_single_def_use_links ();
1408*e4b17023SJohn Marino   df_set_flags (DF_DEFER_INSN_RESCAN);
1409*e4b17023SJohn Marino 
1410*e4b17023SJohn Marino   active_defs = XNEWVEC (df_ref, max_reg_num ());
1411*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1412*e4b17023SJohn Marino   active_defs_check = sparseset_alloc (max_reg_num ());
1413*e4b17023SJohn Marino #endif
1414*e4b17023SJohn Marino }
1415*e4b17023SJohn Marino 
1416*e4b17023SJohn Marino static void
fwprop_done(void)1417*e4b17023SJohn Marino fwprop_done (void)
1418*e4b17023SJohn Marino {
1419*e4b17023SJohn Marino   loop_optimizer_finalize ();
1420*e4b17023SJohn Marino 
1421*e4b17023SJohn Marino   VEC_free (df_ref, heap, use_def_ref);
1422*e4b17023SJohn Marino   free (active_defs);
1423*e4b17023SJohn Marino #ifdef ENABLE_CHECKING
1424*e4b17023SJohn Marino   sparseset_free (active_defs_check);
1425*e4b17023SJohn Marino #endif
1426*e4b17023SJohn Marino 
1427*e4b17023SJohn Marino   free_dominance_info (CDI_DOMINATORS);
1428*e4b17023SJohn Marino   cleanup_cfg (0);
1429*e4b17023SJohn Marino   delete_trivially_dead_insns (get_insns (), max_reg_num ());
1430*e4b17023SJohn Marino 
1431*e4b17023SJohn Marino   if (dump_file)
1432*e4b17023SJohn Marino     fprintf (dump_file,
1433*e4b17023SJohn Marino 	     "\nNumber of successful forward propagations: %d\n\n",
1434*e4b17023SJohn Marino 	     num_changes);
1435*e4b17023SJohn Marino }
1436*e4b17023SJohn Marino 
1437*e4b17023SJohn Marino 
1438*e4b17023SJohn Marino /* Main entry point.  */
1439*e4b17023SJohn Marino 
1440*e4b17023SJohn Marino static bool
gate_fwprop(void)1441*e4b17023SJohn Marino gate_fwprop (void)
1442*e4b17023SJohn Marino {
1443*e4b17023SJohn Marino   return optimize > 0 && flag_forward_propagate;
1444*e4b17023SJohn Marino }
1445*e4b17023SJohn Marino 
1446*e4b17023SJohn Marino static unsigned int
fwprop(void)1447*e4b17023SJohn Marino fwprop (void)
1448*e4b17023SJohn Marino {
1449*e4b17023SJohn Marino   unsigned i;
1450*e4b17023SJohn Marino   bool need_cleanup = false;
1451*e4b17023SJohn Marino 
1452*e4b17023SJohn Marino   fwprop_init ();
1453*e4b17023SJohn Marino 
1454*e4b17023SJohn Marino   /* Go through all the uses.  df_uses_create will create new ones at the
1455*e4b17023SJohn Marino      end, and we'll go through them as well.
1456*e4b17023SJohn Marino 
1457*e4b17023SJohn Marino      Do not forward propagate addresses into loops until after unrolling.
1458*e4b17023SJohn Marino      CSE did so because it was able to fix its own mess, but we are not.  */
1459*e4b17023SJohn Marino 
1460*e4b17023SJohn Marino   for (i = 0; i < DF_USES_TABLE_SIZE (); i++)
1461*e4b17023SJohn Marino     {
1462*e4b17023SJohn Marino       df_ref use = DF_USES_GET (i);
1463*e4b17023SJohn Marino       if (use)
1464*e4b17023SJohn Marino 	if (DF_REF_TYPE (use) == DF_REF_REG_USE
1465*e4b17023SJohn Marino 	    || DF_REF_BB (use)->loop_father == NULL
1466*e4b17023SJohn Marino 	    /* The outer most loop is not really a loop.  */
1467*e4b17023SJohn Marino 	    || loop_outer (DF_REF_BB (use)->loop_father) == NULL)
1468*e4b17023SJohn Marino 	  need_cleanup |= forward_propagate_into (use);
1469*e4b17023SJohn Marino     }
1470*e4b17023SJohn Marino 
1471*e4b17023SJohn Marino   fwprop_done ();
1472*e4b17023SJohn Marino   if (need_cleanup)
1473*e4b17023SJohn Marino     cleanup_cfg (0);
1474*e4b17023SJohn Marino   return 0;
1475*e4b17023SJohn Marino }
1476*e4b17023SJohn Marino 
1477*e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_fwprop =
1478*e4b17023SJohn Marino {
1479*e4b17023SJohn Marino  {
1480*e4b17023SJohn Marino   RTL_PASS,
1481*e4b17023SJohn Marino   "fwprop1",                            /* name */
1482*e4b17023SJohn Marino   gate_fwprop,				/* gate */
1483*e4b17023SJohn Marino   fwprop,				/* execute */
1484*e4b17023SJohn Marino   NULL,                                 /* sub */
1485*e4b17023SJohn Marino   NULL,                                 /* next */
1486*e4b17023SJohn Marino   0,                                    /* static_pass_number */
1487*e4b17023SJohn Marino   TV_FWPROP,                            /* tv_id */
1488*e4b17023SJohn Marino   0,                                    /* properties_required */
1489*e4b17023SJohn Marino   0,                                    /* properties_provided */
1490*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
1491*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
1492*e4b17023SJohn Marino   TODO_df_finish
1493*e4b17023SJohn Marino     | TODO_verify_flow
1494*e4b17023SJohn Marino     | TODO_verify_rtl_sharing           /* todo_flags_finish */
1495*e4b17023SJohn Marino  }
1496*e4b17023SJohn Marino };
1497*e4b17023SJohn Marino 
1498*e4b17023SJohn Marino static unsigned int
fwprop_addr(void)1499*e4b17023SJohn Marino fwprop_addr (void)
1500*e4b17023SJohn Marino {
1501*e4b17023SJohn Marino   unsigned i;
1502*e4b17023SJohn Marino   bool need_cleanup = false;
1503*e4b17023SJohn Marino 
1504*e4b17023SJohn Marino   fwprop_init ();
1505*e4b17023SJohn Marino 
1506*e4b17023SJohn Marino   /* Go through all the uses.  df_uses_create will create new ones at the
1507*e4b17023SJohn Marino      end, and we'll go through them as well.  */
1508*e4b17023SJohn Marino   for (i = 0; i < DF_USES_TABLE_SIZE (); i++)
1509*e4b17023SJohn Marino     {
1510*e4b17023SJohn Marino       df_ref use = DF_USES_GET (i);
1511*e4b17023SJohn Marino       if (use)
1512*e4b17023SJohn Marino 	if (DF_REF_TYPE (use) != DF_REF_REG_USE
1513*e4b17023SJohn Marino 	    && DF_REF_BB (use)->loop_father != NULL
1514*e4b17023SJohn Marino 	    /* The outer most loop is not really a loop.  */
1515*e4b17023SJohn Marino 	    && loop_outer (DF_REF_BB (use)->loop_father) != NULL)
1516*e4b17023SJohn Marino 	  need_cleanup |= forward_propagate_into (use);
1517*e4b17023SJohn Marino     }
1518*e4b17023SJohn Marino 
1519*e4b17023SJohn Marino   fwprop_done ();
1520*e4b17023SJohn Marino 
1521*e4b17023SJohn Marino   if (need_cleanup)
1522*e4b17023SJohn Marino     cleanup_cfg (0);
1523*e4b17023SJohn Marino   return 0;
1524*e4b17023SJohn Marino }
1525*e4b17023SJohn Marino 
1526*e4b17023SJohn Marino struct rtl_opt_pass pass_rtl_fwprop_addr =
1527*e4b17023SJohn Marino {
1528*e4b17023SJohn Marino  {
1529*e4b17023SJohn Marino   RTL_PASS,
1530*e4b17023SJohn Marino   "fwprop2",                            /* name */
1531*e4b17023SJohn Marino   gate_fwprop,				/* gate */
1532*e4b17023SJohn Marino   fwprop_addr,				/* execute */
1533*e4b17023SJohn Marino   NULL,                                 /* sub */
1534*e4b17023SJohn Marino   NULL,                                 /* next */
1535*e4b17023SJohn Marino   0,                                    /* static_pass_number */
1536*e4b17023SJohn Marino   TV_FWPROP,                            /* tv_id */
1537*e4b17023SJohn Marino   0,                                    /* properties_required */
1538*e4b17023SJohn Marino   0,                                    /* properties_provided */
1539*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
1540*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
1541*e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing  /* todo_flags_finish */
1542*e4b17023SJohn Marino  }
1543*e4b17023SJohn Marino };
1544