xref: /dflybsd-src/contrib/gcc-4.7/gcc/lower-subreg.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Decompose multiword subregs.
2*e4b17023SJohn Marino    Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Richard Henderson <rth@redhat.com>
5*e4b17023SJohn Marino 		  Ian Lance Taylor <iant@google.com>
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino This file is part of GCC.
8*e4b17023SJohn Marino 
9*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
10*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
11*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
12*e4b17023SJohn Marino version.
13*e4b17023SJohn Marino 
14*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
16*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17*e4b17023SJohn Marino for more details.
18*e4b17023SJohn Marino 
19*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
20*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
21*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
22*e4b17023SJohn Marino 
23*e4b17023SJohn Marino #include "config.h"
24*e4b17023SJohn Marino #include "system.h"
25*e4b17023SJohn Marino #include "coretypes.h"
26*e4b17023SJohn Marino #include "machmode.h"
27*e4b17023SJohn Marino #include "tm.h"
28*e4b17023SJohn Marino #include "rtl.h"
29*e4b17023SJohn Marino #include "tm_p.h"
30*e4b17023SJohn Marino #include "timevar.h"
31*e4b17023SJohn Marino #include "flags.h"
32*e4b17023SJohn Marino #include "insn-config.h"
33*e4b17023SJohn Marino #include "obstack.h"
34*e4b17023SJohn Marino #include "basic-block.h"
35*e4b17023SJohn Marino #include "recog.h"
36*e4b17023SJohn Marino #include "bitmap.h"
37*e4b17023SJohn Marino #include "dce.h"
38*e4b17023SJohn Marino #include "expr.h"
39*e4b17023SJohn Marino #include "except.h"
40*e4b17023SJohn Marino #include "regs.h"
41*e4b17023SJohn Marino #include "tree-pass.h"
42*e4b17023SJohn Marino #include "df.h"
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino #ifdef STACK_GROWS_DOWNWARD
45*e4b17023SJohn Marino # undef STACK_GROWS_DOWNWARD
46*e4b17023SJohn Marino # define STACK_GROWS_DOWNWARD 1
47*e4b17023SJohn Marino #else
48*e4b17023SJohn Marino # define STACK_GROWS_DOWNWARD 0
49*e4b17023SJohn Marino #endif
50*e4b17023SJohn Marino 
51*e4b17023SJohn Marino DEF_VEC_P (bitmap);
52*e4b17023SJohn Marino DEF_VEC_ALLOC_P (bitmap,heap);
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino /* Decompose multi-word pseudo-registers into individual
55*e4b17023SJohn Marino    pseudo-registers when possible.  This is possible when all the uses
56*e4b17023SJohn Marino    of a multi-word register are via SUBREG, or are copies of the
57*e4b17023SJohn Marino    register to another location.  Breaking apart the register permits
58*e4b17023SJohn Marino    more CSE and permits better register allocation.  */
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino /* Bit N in this bitmap is set if regno N is used in a context in
61*e4b17023SJohn Marino    which we can decompose it.  */
62*e4b17023SJohn Marino static bitmap decomposable_context;
63*e4b17023SJohn Marino 
64*e4b17023SJohn Marino /* Bit N in this bitmap is set if regno N is used in a context in
65*e4b17023SJohn Marino    which it can not be decomposed.  */
66*e4b17023SJohn Marino static bitmap non_decomposable_context;
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino /* Bit N in this bitmap is set if regno N is used in a subreg
69*e4b17023SJohn Marino    which changes the mode but not the size.  This typically happens
70*e4b17023SJohn Marino    when the register accessed as a floating-point value; we want to
71*e4b17023SJohn Marino    avoid generating accesses to its subwords in integer modes.  */
72*e4b17023SJohn Marino static bitmap subreg_context;
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino /* Bit N in the bitmap in element M of this array is set if there is a
75*e4b17023SJohn Marino    copy from reg M to reg N.  */
VEC(bitmap,heap)76*e4b17023SJohn Marino static VEC(bitmap,heap) *reg_copy_graph;
77*e4b17023SJohn Marino 
78*e4b17023SJohn Marino /* Return whether X is a simple object which we can take a word_mode
79*e4b17023SJohn Marino    subreg of.  */
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino static bool
82*e4b17023SJohn Marino simple_move_operand (rtx x)
83*e4b17023SJohn Marino {
84*e4b17023SJohn Marino   if (GET_CODE (x) == SUBREG)
85*e4b17023SJohn Marino     x = SUBREG_REG (x);
86*e4b17023SJohn Marino 
87*e4b17023SJohn Marino   if (!OBJECT_P (x))
88*e4b17023SJohn Marino     return false;
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino   if (GET_CODE (x) == LABEL_REF
91*e4b17023SJohn Marino       || GET_CODE (x) == SYMBOL_REF
92*e4b17023SJohn Marino       || GET_CODE (x) == HIGH
93*e4b17023SJohn Marino       || GET_CODE (x) == CONST)
94*e4b17023SJohn Marino     return false;
95*e4b17023SJohn Marino 
96*e4b17023SJohn Marino   if (MEM_P (x)
97*e4b17023SJohn Marino       && (MEM_VOLATILE_P (x)
98*e4b17023SJohn Marino 	  || mode_dependent_address_p (XEXP (x, 0))))
99*e4b17023SJohn Marino     return false;
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino   return true;
102*e4b17023SJohn Marino }
103*e4b17023SJohn Marino 
104*e4b17023SJohn Marino /* If INSN is a single set between two objects, return the single set.
105*e4b17023SJohn Marino    Such an insn can always be decomposed.  INSN should have been
106*e4b17023SJohn Marino    passed to recog and extract_insn before this is called.  */
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino static rtx
simple_move(rtx insn)109*e4b17023SJohn Marino simple_move (rtx insn)
110*e4b17023SJohn Marino {
111*e4b17023SJohn Marino   rtx x;
112*e4b17023SJohn Marino   rtx set;
113*e4b17023SJohn Marino   enum machine_mode mode;
114*e4b17023SJohn Marino 
115*e4b17023SJohn Marino   if (recog_data.n_operands != 2)
116*e4b17023SJohn Marino     return NULL_RTX;
117*e4b17023SJohn Marino 
118*e4b17023SJohn Marino   set = single_set (insn);
119*e4b17023SJohn Marino   if (!set)
120*e4b17023SJohn Marino     return NULL_RTX;
121*e4b17023SJohn Marino 
122*e4b17023SJohn Marino   x = SET_DEST (set);
123*e4b17023SJohn Marino   if (x != recog_data.operand[0] && x != recog_data.operand[1])
124*e4b17023SJohn Marino     return NULL_RTX;
125*e4b17023SJohn Marino   if (!simple_move_operand (x))
126*e4b17023SJohn Marino     return NULL_RTX;
127*e4b17023SJohn Marino 
128*e4b17023SJohn Marino   x = SET_SRC (set);
129*e4b17023SJohn Marino   if (x != recog_data.operand[0] && x != recog_data.operand[1])
130*e4b17023SJohn Marino     return NULL_RTX;
131*e4b17023SJohn Marino   /* For the src we can handle ASM_OPERANDS, and it is beneficial for
132*e4b17023SJohn Marino      things like x86 rdtsc which returns a DImode value.  */
133*e4b17023SJohn Marino   if (GET_CODE (x) != ASM_OPERANDS
134*e4b17023SJohn Marino       && !simple_move_operand (x))
135*e4b17023SJohn Marino     return NULL_RTX;
136*e4b17023SJohn Marino 
137*e4b17023SJohn Marino   /* We try to decompose in integer modes, to avoid generating
138*e4b17023SJohn Marino      inefficient code copying between integer and floating point
139*e4b17023SJohn Marino      registers.  That means that we can't decompose if this is a
140*e4b17023SJohn Marino      non-integer mode for which there is no integer mode of the same
141*e4b17023SJohn Marino      size.  */
142*e4b17023SJohn Marino   mode = GET_MODE (SET_SRC (set));
143*e4b17023SJohn Marino   if (!SCALAR_INT_MODE_P (mode)
144*e4b17023SJohn Marino       && (mode_for_size (GET_MODE_SIZE (mode) * BITS_PER_UNIT, MODE_INT, 0)
145*e4b17023SJohn Marino 	  == BLKmode))
146*e4b17023SJohn Marino     return NULL_RTX;
147*e4b17023SJohn Marino 
148*e4b17023SJohn Marino   /* Reject PARTIAL_INT modes.  They are used for processor specific
149*e4b17023SJohn Marino      purposes and it's probably best not to tamper with them.  */
150*e4b17023SJohn Marino   if (GET_MODE_CLASS (mode) == MODE_PARTIAL_INT)
151*e4b17023SJohn Marino     return NULL_RTX;
152*e4b17023SJohn Marino 
153*e4b17023SJohn Marino   return set;
154*e4b17023SJohn Marino }
155*e4b17023SJohn Marino 
156*e4b17023SJohn Marino /* If SET is a copy from one multi-word pseudo-register to another,
157*e4b17023SJohn Marino    record that in reg_copy_graph.  Return whether it is such a
158*e4b17023SJohn Marino    copy.  */
159*e4b17023SJohn Marino 
160*e4b17023SJohn Marino static bool
find_pseudo_copy(rtx set)161*e4b17023SJohn Marino find_pseudo_copy (rtx set)
162*e4b17023SJohn Marino {
163*e4b17023SJohn Marino   rtx dest = SET_DEST (set);
164*e4b17023SJohn Marino   rtx src = SET_SRC (set);
165*e4b17023SJohn Marino   unsigned int rd, rs;
166*e4b17023SJohn Marino   bitmap b;
167*e4b17023SJohn Marino 
168*e4b17023SJohn Marino   if (!REG_P (dest) || !REG_P (src))
169*e4b17023SJohn Marino     return false;
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino   rd = REGNO (dest);
172*e4b17023SJohn Marino   rs = REGNO (src);
173*e4b17023SJohn Marino   if (HARD_REGISTER_NUM_P (rd) || HARD_REGISTER_NUM_P (rs))
174*e4b17023SJohn Marino     return false;
175*e4b17023SJohn Marino 
176*e4b17023SJohn Marino   if (GET_MODE_SIZE (GET_MODE (dest)) <= UNITS_PER_WORD)
177*e4b17023SJohn Marino     return false;
178*e4b17023SJohn Marino 
179*e4b17023SJohn Marino   b = VEC_index (bitmap, reg_copy_graph, rs);
180*e4b17023SJohn Marino   if (b == NULL)
181*e4b17023SJohn Marino     {
182*e4b17023SJohn Marino       b = BITMAP_ALLOC (NULL);
183*e4b17023SJohn Marino       VEC_replace (bitmap, reg_copy_graph, rs, b);
184*e4b17023SJohn Marino     }
185*e4b17023SJohn Marino 
186*e4b17023SJohn Marino   bitmap_set_bit (b, rd);
187*e4b17023SJohn Marino 
188*e4b17023SJohn Marino   return true;
189*e4b17023SJohn Marino }
190*e4b17023SJohn Marino 
191*e4b17023SJohn Marino /* Look through the registers in DECOMPOSABLE_CONTEXT.  For each case
192*e4b17023SJohn Marino    where they are copied to another register, add the register to
193*e4b17023SJohn Marino    which they are copied to DECOMPOSABLE_CONTEXT.  Use
194*e4b17023SJohn Marino    NON_DECOMPOSABLE_CONTEXT to limit this--we don't bother to track
195*e4b17023SJohn Marino    copies of registers which are in NON_DECOMPOSABLE_CONTEXT.  */
196*e4b17023SJohn Marino 
197*e4b17023SJohn Marino static void
propagate_pseudo_copies(void)198*e4b17023SJohn Marino propagate_pseudo_copies (void)
199*e4b17023SJohn Marino {
200*e4b17023SJohn Marino   bitmap queue, propagate;
201*e4b17023SJohn Marino 
202*e4b17023SJohn Marino   queue = BITMAP_ALLOC (NULL);
203*e4b17023SJohn Marino   propagate = BITMAP_ALLOC (NULL);
204*e4b17023SJohn Marino 
205*e4b17023SJohn Marino   bitmap_copy (queue, decomposable_context);
206*e4b17023SJohn Marino   do
207*e4b17023SJohn Marino     {
208*e4b17023SJohn Marino       bitmap_iterator iter;
209*e4b17023SJohn Marino       unsigned int i;
210*e4b17023SJohn Marino 
211*e4b17023SJohn Marino       bitmap_clear (propagate);
212*e4b17023SJohn Marino 
213*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (queue, 0, i, iter)
214*e4b17023SJohn Marino 	{
215*e4b17023SJohn Marino 	  bitmap b = VEC_index (bitmap, reg_copy_graph, i);
216*e4b17023SJohn Marino 	  if (b)
217*e4b17023SJohn Marino 	    bitmap_ior_and_compl_into (propagate, b, non_decomposable_context);
218*e4b17023SJohn Marino 	}
219*e4b17023SJohn Marino 
220*e4b17023SJohn Marino       bitmap_and_compl (queue, propagate, decomposable_context);
221*e4b17023SJohn Marino       bitmap_ior_into (decomposable_context, propagate);
222*e4b17023SJohn Marino     }
223*e4b17023SJohn Marino   while (!bitmap_empty_p (queue));
224*e4b17023SJohn Marino 
225*e4b17023SJohn Marino   BITMAP_FREE (queue);
226*e4b17023SJohn Marino   BITMAP_FREE (propagate);
227*e4b17023SJohn Marino }
228*e4b17023SJohn Marino 
229*e4b17023SJohn Marino /* A pointer to one of these values is passed to
230*e4b17023SJohn Marino    find_decomposable_subregs via for_each_rtx.  */
231*e4b17023SJohn Marino 
232*e4b17023SJohn Marino enum classify_move_insn
233*e4b17023SJohn Marino {
234*e4b17023SJohn Marino   /* Not a simple move from one location to another.  */
235*e4b17023SJohn Marino   NOT_SIMPLE_MOVE,
236*e4b17023SJohn Marino   /* A simple move from one pseudo-register to another.  */
237*e4b17023SJohn Marino   SIMPLE_PSEUDO_REG_MOVE,
238*e4b17023SJohn Marino   /* A simple move involving a non-pseudo-register.  */
239*e4b17023SJohn Marino   SIMPLE_MOVE
240*e4b17023SJohn Marino };
241*e4b17023SJohn Marino 
242*e4b17023SJohn Marino /* This is called via for_each_rtx.  If we find a SUBREG which we
243*e4b17023SJohn Marino    could use to decompose a pseudo-register, set a bit in
244*e4b17023SJohn Marino    DECOMPOSABLE_CONTEXT.  If we find an unadorned register which is
245*e4b17023SJohn Marino    not a simple pseudo-register copy, DATA will point at the type of
246*e4b17023SJohn Marino    move, and we set a bit in DECOMPOSABLE_CONTEXT or
247*e4b17023SJohn Marino    NON_DECOMPOSABLE_CONTEXT as appropriate.  */
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino static int
find_decomposable_subregs(rtx * px,void * data)250*e4b17023SJohn Marino find_decomposable_subregs (rtx *px, void *data)
251*e4b17023SJohn Marino {
252*e4b17023SJohn Marino   enum classify_move_insn *pcmi = (enum classify_move_insn *) data;
253*e4b17023SJohn Marino   rtx x = *px;
254*e4b17023SJohn Marino 
255*e4b17023SJohn Marino   if (x == NULL_RTX)
256*e4b17023SJohn Marino     return 0;
257*e4b17023SJohn Marino 
258*e4b17023SJohn Marino   if (GET_CODE (x) == SUBREG)
259*e4b17023SJohn Marino     {
260*e4b17023SJohn Marino       rtx inner = SUBREG_REG (x);
261*e4b17023SJohn Marino       unsigned int regno, outer_size, inner_size, outer_words, inner_words;
262*e4b17023SJohn Marino 
263*e4b17023SJohn Marino       if (!REG_P (inner))
264*e4b17023SJohn Marino 	return 0;
265*e4b17023SJohn Marino 
266*e4b17023SJohn Marino       regno = REGNO (inner);
267*e4b17023SJohn Marino       if (HARD_REGISTER_NUM_P (regno))
268*e4b17023SJohn Marino 	return -1;
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino       outer_size = GET_MODE_SIZE (GET_MODE (x));
271*e4b17023SJohn Marino       inner_size = GET_MODE_SIZE (GET_MODE (inner));
272*e4b17023SJohn Marino       outer_words = (outer_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
273*e4b17023SJohn Marino       inner_words = (inner_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
274*e4b17023SJohn Marino 
275*e4b17023SJohn Marino       /* We only try to decompose single word subregs of multi-word
276*e4b17023SJohn Marino 	 registers.  When we find one, we return -1 to avoid iterating
277*e4b17023SJohn Marino 	 over the inner register.
278*e4b17023SJohn Marino 
279*e4b17023SJohn Marino 	 ??? This doesn't allow, e.g., DImode subregs of TImode values
280*e4b17023SJohn Marino 	 on 32-bit targets.  We would need to record the way the
281*e4b17023SJohn Marino 	 pseudo-register was used, and only decompose if all the uses
282*e4b17023SJohn Marino 	 were the same number and size of pieces.  Hopefully this
283*e4b17023SJohn Marino 	 doesn't happen much.  */
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino       if (outer_words == 1 && inner_words > 1)
286*e4b17023SJohn Marino 	{
287*e4b17023SJohn Marino 	  bitmap_set_bit (decomposable_context, regno);
288*e4b17023SJohn Marino 	  return -1;
289*e4b17023SJohn Marino 	}
290*e4b17023SJohn Marino 
291*e4b17023SJohn Marino       /* If this is a cast from one mode to another, where the modes
292*e4b17023SJohn Marino 	 have the same size, and they are not tieable, then mark this
293*e4b17023SJohn Marino 	 register as non-decomposable.  If we decompose it we are
294*e4b17023SJohn Marino 	 likely to mess up whatever the backend is trying to do.  */
295*e4b17023SJohn Marino       if (outer_words > 1
296*e4b17023SJohn Marino 	  && outer_size == inner_size
297*e4b17023SJohn Marino 	  && !MODES_TIEABLE_P (GET_MODE (x), GET_MODE (inner)))
298*e4b17023SJohn Marino 	{
299*e4b17023SJohn Marino 	  bitmap_set_bit (non_decomposable_context, regno);
300*e4b17023SJohn Marino 	  bitmap_set_bit (subreg_context, regno);
301*e4b17023SJohn Marino 	  return -1;
302*e4b17023SJohn Marino 	}
303*e4b17023SJohn Marino     }
304*e4b17023SJohn Marino   else if (REG_P (x))
305*e4b17023SJohn Marino     {
306*e4b17023SJohn Marino       unsigned int regno;
307*e4b17023SJohn Marino 
308*e4b17023SJohn Marino       /* We will see an outer SUBREG before we see the inner REG, so
309*e4b17023SJohn Marino 	 when we see a plain REG here it means a direct reference to
310*e4b17023SJohn Marino 	 the register.
311*e4b17023SJohn Marino 
312*e4b17023SJohn Marino 	 If this is not a simple copy from one location to another,
313*e4b17023SJohn Marino 	 then we can not decompose this register.  If this is a simple
314*e4b17023SJohn Marino 	 copy from one pseudo-register to another, and the mode is right
315*e4b17023SJohn Marino 	 then we mark the register as decomposable.
316*e4b17023SJohn Marino 	 Otherwise we don't say anything about this register --
317*e4b17023SJohn Marino 	 it could be decomposed, but whether that would be
318*e4b17023SJohn Marino 	 profitable depends upon how it is used elsewhere.
319*e4b17023SJohn Marino 
320*e4b17023SJohn Marino 	 We only set bits in the bitmap for multi-word
321*e4b17023SJohn Marino 	 pseudo-registers, since those are the only ones we care about
322*e4b17023SJohn Marino 	 and it keeps the size of the bitmaps down.  */
323*e4b17023SJohn Marino 
324*e4b17023SJohn Marino       regno = REGNO (x);
325*e4b17023SJohn Marino       if (!HARD_REGISTER_NUM_P (regno)
326*e4b17023SJohn Marino 	  && GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
327*e4b17023SJohn Marino 	{
328*e4b17023SJohn Marino 	  switch (*pcmi)
329*e4b17023SJohn Marino 	    {
330*e4b17023SJohn Marino 	    case NOT_SIMPLE_MOVE:
331*e4b17023SJohn Marino 	      bitmap_set_bit (non_decomposable_context, regno);
332*e4b17023SJohn Marino 	      break;
333*e4b17023SJohn Marino 	    case SIMPLE_PSEUDO_REG_MOVE:
334*e4b17023SJohn Marino 	      if (MODES_TIEABLE_P (GET_MODE (x), word_mode))
335*e4b17023SJohn Marino 		bitmap_set_bit (decomposable_context, regno);
336*e4b17023SJohn Marino 	      break;
337*e4b17023SJohn Marino 	    case SIMPLE_MOVE:
338*e4b17023SJohn Marino 	      break;
339*e4b17023SJohn Marino 	    default:
340*e4b17023SJohn Marino 	      gcc_unreachable ();
341*e4b17023SJohn Marino 	    }
342*e4b17023SJohn Marino 	}
343*e4b17023SJohn Marino     }
344*e4b17023SJohn Marino   else if (MEM_P (x))
345*e4b17023SJohn Marino     {
346*e4b17023SJohn Marino       enum classify_move_insn cmi_mem = NOT_SIMPLE_MOVE;
347*e4b17023SJohn Marino 
348*e4b17023SJohn Marino       /* Any registers used in a MEM do not participate in a
349*e4b17023SJohn Marino 	 SIMPLE_MOVE or SIMPLE_PSEUDO_REG_MOVE.  Do our own recursion
350*e4b17023SJohn Marino 	 here, and return -1 to block the parent's recursion.  */
351*e4b17023SJohn Marino       for_each_rtx (&XEXP (x, 0), find_decomposable_subregs, &cmi_mem);
352*e4b17023SJohn Marino       return -1;
353*e4b17023SJohn Marino     }
354*e4b17023SJohn Marino 
355*e4b17023SJohn Marino   return 0;
356*e4b17023SJohn Marino }
357*e4b17023SJohn Marino 
358*e4b17023SJohn Marino /* Decompose REGNO into word-sized components.  We smash the REG node
359*e4b17023SJohn Marino    in place.  This ensures that (1) something goes wrong quickly if we
360*e4b17023SJohn Marino    fail to make some replacement, and (2) the debug information inside
361*e4b17023SJohn Marino    the symbol table is automatically kept up to date.  */
362*e4b17023SJohn Marino 
363*e4b17023SJohn Marino static void
decompose_register(unsigned int regno)364*e4b17023SJohn Marino decompose_register (unsigned int regno)
365*e4b17023SJohn Marino {
366*e4b17023SJohn Marino   rtx reg;
367*e4b17023SJohn Marino   unsigned int words, i;
368*e4b17023SJohn Marino   rtvec v;
369*e4b17023SJohn Marino 
370*e4b17023SJohn Marino   reg = regno_reg_rtx[regno];
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino   regno_reg_rtx[regno] = NULL_RTX;
373*e4b17023SJohn Marino 
374*e4b17023SJohn Marino   words = GET_MODE_SIZE (GET_MODE (reg));
375*e4b17023SJohn Marino   words = (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
376*e4b17023SJohn Marino 
377*e4b17023SJohn Marino   v = rtvec_alloc (words);
378*e4b17023SJohn Marino   for (i = 0; i < words; ++i)
379*e4b17023SJohn Marino     RTVEC_ELT (v, i) = gen_reg_rtx_offset (reg, word_mode, i * UNITS_PER_WORD);
380*e4b17023SJohn Marino 
381*e4b17023SJohn Marino   PUT_CODE (reg, CONCATN);
382*e4b17023SJohn Marino   XVEC (reg, 0) = v;
383*e4b17023SJohn Marino 
384*e4b17023SJohn Marino   if (dump_file)
385*e4b17023SJohn Marino     {
386*e4b17023SJohn Marino       fprintf (dump_file, "; Splitting reg %u ->", regno);
387*e4b17023SJohn Marino       for (i = 0; i < words; ++i)
388*e4b17023SJohn Marino 	fprintf (dump_file, " %u", REGNO (XVECEXP (reg, 0, i)));
389*e4b17023SJohn Marino       fputc ('\n', dump_file);
390*e4b17023SJohn Marino     }
391*e4b17023SJohn Marino }
392*e4b17023SJohn Marino 
393*e4b17023SJohn Marino /* Get a SUBREG of a CONCATN.  */
394*e4b17023SJohn Marino 
395*e4b17023SJohn Marino static rtx
simplify_subreg_concatn(enum machine_mode outermode,rtx op,unsigned int byte)396*e4b17023SJohn Marino simplify_subreg_concatn (enum machine_mode outermode, rtx op,
397*e4b17023SJohn Marino 			 unsigned int byte)
398*e4b17023SJohn Marino {
399*e4b17023SJohn Marino   unsigned int inner_size;
400*e4b17023SJohn Marino   enum machine_mode innermode, partmode;
401*e4b17023SJohn Marino   rtx part;
402*e4b17023SJohn Marino   unsigned int final_offset;
403*e4b17023SJohn Marino 
404*e4b17023SJohn Marino   gcc_assert (GET_CODE (op) == CONCATN);
405*e4b17023SJohn Marino   gcc_assert (byte % GET_MODE_SIZE (outermode) == 0);
406*e4b17023SJohn Marino 
407*e4b17023SJohn Marino   innermode = GET_MODE (op);
408*e4b17023SJohn Marino   gcc_assert (byte < GET_MODE_SIZE (innermode));
409*e4b17023SJohn Marino   gcc_assert (GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (innermode));
410*e4b17023SJohn Marino 
411*e4b17023SJohn Marino   inner_size = GET_MODE_SIZE (innermode) / XVECLEN (op, 0);
412*e4b17023SJohn Marino   part = XVECEXP (op, 0, byte / inner_size);
413*e4b17023SJohn Marino   partmode = GET_MODE (part);
414*e4b17023SJohn Marino 
415*e4b17023SJohn Marino   /* VECTOR_CSTs in debug expressions are expanded into CONCATN instead of
416*e4b17023SJohn Marino      regular CONST_VECTORs.  They have vector or integer modes, depending
417*e4b17023SJohn Marino      on the capabilities of the target.  Cope with them.  */
418*e4b17023SJohn Marino   if (partmode == VOIDmode && VECTOR_MODE_P (innermode))
419*e4b17023SJohn Marino     partmode = GET_MODE_INNER (innermode);
420*e4b17023SJohn Marino   else if (partmode == VOIDmode)
421*e4b17023SJohn Marino     {
422*e4b17023SJohn Marino       enum mode_class mclass = GET_MODE_CLASS (innermode);
423*e4b17023SJohn Marino       partmode = mode_for_size (inner_size * BITS_PER_UNIT, mclass, 0);
424*e4b17023SJohn Marino     }
425*e4b17023SJohn Marino 
426*e4b17023SJohn Marino   final_offset = byte % inner_size;
427*e4b17023SJohn Marino   if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
428*e4b17023SJohn Marino     return NULL_RTX;
429*e4b17023SJohn Marino 
430*e4b17023SJohn Marino   return simplify_gen_subreg (outermode, part, partmode, final_offset);
431*e4b17023SJohn Marino }
432*e4b17023SJohn Marino 
433*e4b17023SJohn Marino /* Wrapper around simplify_gen_subreg which handles CONCATN.  */
434*e4b17023SJohn Marino 
435*e4b17023SJohn Marino static rtx
simplify_gen_subreg_concatn(enum machine_mode outermode,rtx op,enum machine_mode innermode,unsigned int byte)436*e4b17023SJohn Marino simplify_gen_subreg_concatn (enum machine_mode outermode, rtx op,
437*e4b17023SJohn Marino 			     enum machine_mode innermode, unsigned int byte)
438*e4b17023SJohn Marino {
439*e4b17023SJohn Marino   rtx ret;
440*e4b17023SJohn Marino 
441*e4b17023SJohn Marino   /* We have to handle generating a SUBREG of a SUBREG of a CONCATN.
442*e4b17023SJohn Marino      If OP is a SUBREG of a CONCATN, then it must be a simple mode
443*e4b17023SJohn Marino      change with the same size and offset 0, or it must extract a
444*e4b17023SJohn Marino      part.  We shouldn't see anything else here.  */
445*e4b17023SJohn Marino   if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == CONCATN)
446*e4b17023SJohn Marino     {
447*e4b17023SJohn Marino       rtx op2;
448*e4b17023SJohn Marino 
449*e4b17023SJohn Marino       if ((GET_MODE_SIZE (GET_MODE (op))
450*e4b17023SJohn Marino 	   == GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
451*e4b17023SJohn Marino 	  && SUBREG_BYTE (op) == 0)
452*e4b17023SJohn Marino 	return simplify_gen_subreg_concatn (outermode, SUBREG_REG (op),
453*e4b17023SJohn Marino 					    GET_MODE (SUBREG_REG (op)), byte);
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino       op2 = simplify_subreg_concatn (GET_MODE (op), SUBREG_REG (op),
456*e4b17023SJohn Marino 				     SUBREG_BYTE (op));
457*e4b17023SJohn Marino       if (op2 == NULL_RTX)
458*e4b17023SJohn Marino 	{
459*e4b17023SJohn Marino 	  /* We don't handle paradoxical subregs here.  */
460*e4b17023SJohn Marino 	  gcc_assert (GET_MODE_SIZE (outermode)
461*e4b17023SJohn Marino 		      <= GET_MODE_SIZE (GET_MODE (op)));
462*e4b17023SJohn Marino 	  gcc_assert (GET_MODE_SIZE (GET_MODE (op))
463*e4b17023SJohn Marino 		      <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))));
464*e4b17023SJohn Marino 	  op2 = simplify_subreg_concatn (outermode, SUBREG_REG (op),
465*e4b17023SJohn Marino 					 byte + SUBREG_BYTE (op));
466*e4b17023SJohn Marino 	  gcc_assert (op2 != NULL_RTX);
467*e4b17023SJohn Marino 	  return op2;
468*e4b17023SJohn Marino 	}
469*e4b17023SJohn Marino 
470*e4b17023SJohn Marino       op = op2;
471*e4b17023SJohn Marino       gcc_assert (op != NULL_RTX);
472*e4b17023SJohn Marino       gcc_assert (innermode == GET_MODE (op));
473*e4b17023SJohn Marino     }
474*e4b17023SJohn Marino 
475*e4b17023SJohn Marino   if (GET_CODE (op) == CONCATN)
476*e4b17023SJohn Marino     return simplify_subreg_concatn (outermode, op, byte);
477*e4b17023SJohn Marino 
478*e4b17023SJohn Marino   ret = simplify_gen_subreg (outermode, op, innermode, byte);
479*e4b17023SJohn Marino 
480*e4b17023SJohn Marino   /* If we see an insn like (set (reg:DI) (subreg:DI (reg:SI) 0)) then
481*e4b17023SJohn Marino      resolve_simple_move will ask for the high part of the paradoxical
482*e4b17023SJohn Marino      subreg, which does not have a value.  Just return a zero.  */
483*e4b17023SJohn Marino   if (ret == NULL_RTX
484*e4b17023SJohn Marino       && GET_CODE (op) == SUBREG
485*e4b17023SJohn Marino       && SUBREG_BYTE (op) == 0
486*e4b17023SJohn Marino       && (GET_MODE_SIZE (innermode)
487*e4b17023SJohn Marino 	  > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
488*e4b17023SJohn Marino     return CONST0_RTX (outermode);
489*e4b17023SJohn Marino 
490*e4b17023SJohn Marino   gcc_assert (ret != NULL_RTX);
491*e4b17023SJohn Marino   return ret;
492*e4b17023SJohn Marino }
493*e4b17023SJohn Marino 
494*e4b17023SJohn Marino /* Return whether we should resolve X into the registers into which it
495*e4b17023SJohn Marino    was decomposed.  */
496*e4b17023SJohn Marino 
497*e4b17023SJohn Marino static bool
resolve_reg_p(rtx x)498*e4b17023SJohn Marino resolve_reg_p (rtx x)
499*e4b17023SJohn Marino {
500*e4b17023SJohn Marino   return GET_CODE (x) == CONCATN;
501*e4b17023SJohn Marino }
502*e4b17023SJohn Marino 
503*e4b17023SJohn Marino /* Return whether X is a SUBREG of a register which we need to
504*e4b17023SJohn Marino    resolve.  */
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino static bool
resolve_subreg_p(rtx x)507*e4b17023SJohn Marino resolve_subreg_p (rtx x)
508*e4b17023SJohn Marino {
509*e4b17023SJohn Marino   if (GET_CODE (x) != SUBREG)
510*e4b17023SJohn Marino     return false;
511*e4b17023SJohn Marino   return resolve_reg_p (SUBREG_REG (x));
512*e4b17023SJohn Marino }
513*e4b17023SJohn Marino 
514*e4b17023SJohn Marino /* This is called via for_each_rtx.  Look for SUBREGs which need to be
515*e4b17023SJohn Marino    decomposed.  */
516*e4b17023SJohn Marino 
517*e4b17023SJohn Marino static int
resolve_subreg_use(rtx * px,void * data)518*e4b17023SJohn Marino resolve_subreg_use (rtx *px, void *data)
519*e4b17023SJohn Marino {
520*e4b17023SJohn Marino   rtx insn = (rtx) data;
521*e4b17023SJohn Marino   rtx x = *px;
522*e4b17023SJohn Marino 
523*e4b17023SJohn Marino   if (x == NULL_RTX)
524*e4b17023SJohn Marino     return 0;
525*e4b17023SJohn Marino 
526*e4b17023SJohn Marino   if (resolve_subreg_p (x))
527*e4b17023SJohn Marino     {
528*e4b17023SJohn Marino       x = simplify_subreg_concatn (GET_MODE (x), SUBREG_REG (x),
529*e4b17023SJohn Marino 				   SUBREG_BYTE (x));
530*e4b17023SJohn Marino 
531*e4b17023SJohn Marino       /* It is possible for a note to contain a reference which we can
532*e4b17023SJohn Marino 	 decompose.  In this case, return 1 to the caller to indicate
533*e4b17023SJohn Marino 	 that the note must be removed.  */
534*e4b17023SJohn Marino       if (!x)
535*e4b17023SJohn Marino 	{
536*e4b17023SJohn Marino 	  gcc_assert (!insn);
537*e4b17023SJohn Marino 	  return 1;
538*e4b17023SJohn Marino 	}
539*e4b17023SJohn Marino 
540*e4b17023SJohn Marino       validate_change (insn, px, x, 1);
541*e4b17023SJohn Marino       return -1;
542*e4b17023SJohn Marino     }
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino   if (resolve_reg_p (x))
545*e4b17023SJohn Marino     {
546*e4b17023SJohn Marino       /* Return 1 to the caller to indicate that we found a direct
547*e4b17023SJohn Marino 	 reference to a register which is being decomposed.  This can
548*e4b17023SJohn Marino 	 happen inside notes, multiword shift or zero-extend
549*e4b17023SJohn Marino 	 instructions.  */
550*e4b17023SJohn Marino       return 1;
551*e4b17023SJohn Marino     }
552*e4b17023SJohn Marino 
553*e4b17023SJohn Marino   return 0;
554*e4b17023SJohn Marino }
555*e4b17023SJohn Marino 
556*e4b17023SJohn Marino /* This is called via for_each_rtx.  Look for SUBREGs which can be
557*e4b17023SJohn Marino    decomposed and decomposed REGs that need copying.  */
558*e4b17023SJohn Marino 
559*e4b17023SJohn Marino static int
adjust_decomposed_uses(rtx * px,void * data ATTRIBUTE_UNUSED)560*e4b17023SJohn Marino adjust_decomposed_uses (rtx *px, void *data ATTRIBUTE_UNUSED)
561*e4b17023SJohn Marino {
562*e4b17023SJohn Marino   rtx x = *px;
563*e4b17023SJohn Marino 
564*e4b17023SJohn Marino   if (x == NULL_RTX)
565*e4b17023SJohn Marino     return 0;
566*e4b17023SJohn Marino 
567*e4b17023SJohn Marino   if (resolve_subreg_p (x))
568*e4b17023SJohn Marino     {
569*e4b17023SJohn Marino       x = simplify_subreg_concatn (GET_MODE (x), SUBREG_REG (x),
570*e4b17023SJohn Marino 				   SUBREG_BYTE (x));
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino       if (x)
573*e4b17023SJohn Marino 	*px = x;
574*e4b17023SJohn Marino       else
575*e4b17023SJohn Marino 	x = copy_rtx (*px);
576*e4b17023SJohn Marino     }
577*e4b17023SJohn Marino 
578*e4b17023SJohn Marino   if (resolve_reg_p (x))
579*e4b17023SJohn Marino     *px = copy_rtx (x);
580*e4b17023SJohn Marino 
581*e4b17023SJohn Marino   return 0;
582*e4b17023SJohn Marino }
583*e4b17023SJohn Marino 
584*e4b17023SJohn Marino /* Resolve any decomposed registers which appear in register notes on
585*e4b17023SJohn Marino    INSN.  */
586*e4b17023SJohn Marino 
587*e4b17023SJohn Marino static void
resolve_reg_notes(rtx insn)588*e4b17023SJohn Marino resolve_reg_notes (rtx insn)
589*e4b17023SJohn Marino {
590*e4b17023SJohn Marino   rtx *pnote, note;
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino   note = find_reg_equal_equiv_note (insn);
593*e4b17023SJohn Marino   if (note)
594*e4b17023SJohn Marino     {
595*e4b17023SJohn Marino       int old_count = num_validated_changes ();
596*e4b17023SJohn Marino       if (for_each_rtx (&XEXP (note, 0), resolve_subreg_use, NULL))
597*e4b17023SJohn Marino 	remove_note (insn, note);
598*e4b17023SJohn Marino       else
599*e4b17023SJohn Marino 	if (old_count != num_validated_changes ())
600*e4b17023SJohn Marino 	  df_notes_rescan (insn);
601*e4b17023SJohn Marino     }
602*e4b17023SJohn Marino 
603*e4b17023SJohn Marino   pnote = &REG_NOTES (insn);
604*e4b17023SJohn Marino   while (*pnote != NULL_RTX)
605*e4b17023SJohn Marino     {
606*e4b17023SJohn Marino       bool del = false;
607*e4b17023SJohn Marino 
608*e4b17023SJohn Marino       note = *pnote;
609*e4b17023SJohn Marino       switch (REG_NOTE_KIND (note))
610*e4b17023SJohn Marino 	{
611*e4b17023SJohn Marino 	case REG_DEAD:
612*e4b17023SJohn Marino 	case REG_UNUSED:
613*e4b17023SJohn Marino 	  if (resolve_reg_p (XEXP (note, 0)))
614*e4b17023SJohn Marino 	    del = true;
615*e4b17023SJohn Marino 	  break;
616*e4b17023SJohn Marino 
617*e4b17023SJohn Marino 	default:
618*e4b17023SJohn Marino 	  break;
619*e4b17023SJohn Marino 	}
620*e4b17023SJohn Marino 
621*e4b17023SJohn Marino       if (del)
622*e4b17023SJohn Marino 	*pnote = XEXP (note, 1);
623*e4b17023SJohn Marino       else
624*e4b17023SJohn Marino 	pnote = &XEXP (note, 1);
625*e4b17023SJohn Marino     }
626*e4b17023SJohn Marino }
627*e4b17023SJohn Marino 
628*e4b17023SJohn Marino /* Return whether X can be decomposed into subwords.  */
629*e4b17023SJohn Marino 
630*e4b17023SJohn Marino static bool
can_decompose_p(rtx x)631*e4b17023SJohn Marino can_decompose_p (rtx x)
632*e4b17023SJohn Marino {
633*e4b17023SJohn Marino   if (REG_P (x))
634*e4b17023SJohn Marino     {
635*e4b17023SJohn Marino       unsigned int regno = REGNO (x);
636*e4b17023SJohn Marino 
637*e4b17023SJohn Marino       if (HARD_REGISTER_NUM_P (regno))
638*e4b17023SJohn Marino 	{
639*e4b17023SJohn Marino 	  unsigned int byte, num_bytes;
640*e4b17023SJohn Marino 
641*e4b17023SJohn Marino 	  num_bytes = GET_MODE_SIZE (GET_MODE (x));
642*e4b17023SJohn Marino 	  for (byte = 0; byte < num_bytes; byte += UNITS_PER_WORD)
643*e4b17023SJohn Marino 	    if (simplify_subreg_regno (regno, GET_MODE (x), byte, word_mode) < 0)
644*e4b17023SJohn Marino 	      return false;
645*e4b17023SJohn Marino 	  return true;
646*e4b17023SJohn Marino 	}
647*e4b17023SJohn Marino       else
648*e4b17023SJohn Marino 	return !bitmap_bit_p (subreg_context, regno);
649*e4b17023SJohn Marino     }
650*e4b17023SJohn Marino 
651*e4b17023SJohn Marino   return true;
652*e4b17023SJohn Marino }
653*e4b17023SJohn Marino 
654*e4b17023SJohn Marino /* Decompose the registers used in a simple move SET within INSN.  If
655*e4b17023SJohn Marino    we don't change anything, return INSN, otherwise return the start
656*e4b17023SJohn Marino    of the sequence of moves.  */
657*e4b17023SJohn Marino 
658*e4b17023SJohn Marino static rtx
resolve_simple_move(rtx set,rtx insn)659*e4b17023SJohn Marino resolve_simple_move (rtx set, rtx insn)
660*e4b17023SJohn Marino {
661*e4b17023SJohn Marino   rtx src, dest, real_dest, insns;
662*e4b17023SJohn Marino   enum machine_mode orig_mode, dest_mode;
663*e4b17023SJohn Marino   unsigned int words;
664*e4b17023SJohn Marino   bool pushing;
665*e4b17023SJohn Marino 
666*e4b17023SJohn Marino   src = SET_SRC (set);
667*e4b17023SJohn Marino   dest = SET_DEST (set);
668*e4b17023SJohn Marino   orig_mode = GET_MODE (dest);
669*e4b17023SJohn Marino 
670*e4b17023SJohn Marino   words = (GET_MODE_SIZE (orig_mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
671*e4b17023SJohn Marino   if (words <= 1)
672*e4b17023SJohn Marino     return insn;
673*e4b17023SJohn Marino 
674*e4b17023SJohn Marino   start_sequence ();
675*e4b17023SJohn Marino 
676*e4b17023SJohn Marino   /* We have to handle copying from a SUBREG of a decomposed reg where
677*e4b17023SJohn Marino      the SUBREG is larger than word size.  Rather than assume that we
678*e4b17023SJohn Marino      can take a word_mode SUBREG of the destination, we copy to a new
679*e4b17023SJohn Marino      register and then copy that to the destination.  */
680*e4b17023SJohn Marino 
681*e4b17023SJohn Marino   real_dest = NULL_RTX;
682*e4b17023SJohn Marino 
683*e4b17023SJohn Marino   if (GET_CODE (src) == SUBREG
684*e4b17023SJohn Marino       && resolve_reg_p (SUBREG_REG (src))
685*e4b17023SJohn Marino       && (SUBREG_BYTE (src) != 0
686*e4b17023SJohn Marino 	  || (GET_MODE_SIZE (orig_mode)
687*e4b17023SJohn Marino 	      != GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))))
688*e4b17023SJohn Marino     {
689*e4b17023SJohn Marino       real_dest = dest;
690*e4b17023SJohn Marino       dest = gen_reg_rtx (orig_mode);
691*e4b17023SJohn Marino       if (REG_P (real_dest))
692*e4b17023SJohn Marino 	REG_ATTRS (dest) = REG_ATTRS (real_dest);
693*e4b17023SJohn Marino     }
694*e4b17023SJohn Marino 
695*e4b17023SJohn Marino   /* Similarly if we are copying to a SUBREG of a decomposed reg where
696*e4b17023SJohn Marino      the SUBREG is larger than word size.  */
697*e4b17023SJohn Marino 
698*e4b17023SJohn Marino   if (GET_CODE (dest) == SUBREG
699*e4b17023SJohn Marino       && resolve_reg_p (SUBREG_REG (dest))
700*e4b17023SJohn Marino       && (SUBREG_BYTE (dest) != 0
701*e4b17023SJohn Marino 	  || (GET_MODE_SIZE (orig_mode)
702*e4b17023SJohn Marino 	      != GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))))
703*e4b17023SJohn Marino     {
704*e4b17023SJohn Marino       rtx reg, minsn, smove;
705*e4b17023SJohn Marino 
706*e4b17023SJohn Marino       reg = gen_reg_rtx (orig_mode);
707*e4b17023SJohn Marino       minsn = emit_move_insn (reg, src);
708*e4b17023SJohn Marino       smove = single_set (minsn);
709*e4b17023SJohn Marino       gcc_assert (smove != NULL_RTX);
710*e4b17023SJohn Marino       resolve_simple_move (smove, minsn);
711*e4b17023SJohn Marino       src = reg;
712*e4b17023SJohn Marino     }
713*e4b17023SJohn Marino 
714*e4b17023SJohn Marino   /* If we didn't have any big SUBREGS of decomposed registers, and
715*e4b17023SJohn Marino      neither side of the move is a register we are decomposing, then
716*e4b17023SJohn Marino      we don't have to do anything here.  */
717*e4b17023SJohn Marino 
718*e4b17023SJohn Marino   if (src == SET_SRC (set)
719*e4b17023SJohn Marino       && dest == SET_DEST (set)
720*e4b17023SJohn Marino       && !resolve_reg_p (src)
721*e4b17023SJohn Marino       && !resolve_subreg_p (src)
722*e4b17023SJohn Marino       && !resolve_reg_p (dest)
723*e4b17023SJohn Marino       && !resolve_subreg_p (dest))
724*e4b17023SJohn Marino     {
725*e4b17023SJohn Marino       end_sequence ();
726*e4b17023SJohn Marino       return insn;
727*e4b17023SJohn Marino     }
728*e4b17023SJohn Marino 
729*e4b17023SJohn Marino   /* It's possible for the code to use a subreg of a decomposed
730*e4b17023SJohn Marino      register while forming an address.  We need to handle that before
731*e4b17023SJohn Marino      passing the address to emit_move_insn.  We pass NULL_RTX as the
732*e4b17023SJohn Marino      insn parameter to resolve_subreg_use because we can not validate
733*e4b17023SJohn Marino      the insn yet.  */
734*e4b17023SJohn Marino   if (MEM_P (src) || MEM_P (dest))
735*e4b17023SJohn Marino     {
736*e4b17023SJohn Marino       int acg;
737*e4b17023SJohn Marino 
738*e4b17023SJohn Marino       if (MEM_P (src))
739*e4b17023SJohn Marino 	for_each_rtx (&XEXP (src, 0), resolve_subreg_use, NULL_RTX);
740*e4b17023SJohn Marino       if (MEM_P (dest))
741*e4b17023SJohn Marino 	for_each_rtx (&XEXP (dest, 0), resolve_subreg_use, NULL_RTX);
742*e4b17023SJohn Marino       acg = apply_change_group ();
743*e4b17023SJohn Marino       gcc_assert (acg);
744*e4b17023SJohn Marino     }
745*e4b17023SJohn Marino 
746*e4b17023SJohn Marino   /* If SRC is a register which we can't decompose, or has side
747*e4b17023SJohn Marino      effects, we need to move via a temporary register.  */
748*e4b17023SJohn Marino 
749*e4b17023SJohn Marino   if (!can_decompose_p (src)
750*e4b17023SJohn Marino       || side_effects_p (src)
751*e4b17023SJohn Marino       || GET_CODE (src) == ASM_OPERANDS)
752*e4b17023SJohn Marino     {
753*e4b17023SJohn Marino       rtx reg;
754*e4b17023SJohn Marino 
755*e4b17023SJohn Marino       reg = gen_reg_rtx (orig_mode);
756*e4b17023SJohn Marino       emit_move_insn (reg, src);
757*e4b17023SJohn Marino       src = reg;
758*e4b17023SJohn Marino     }
759*e4b17023SJohn Marino 
760*e4b17023SJohn Marino   /* If DEST is a register which we can't decompose, or has side
761*e4b17023SJohn Marino      effects, we need to first move to a temporary register.  We
762*e4b17023SJohn Marino      handle the common case of pushing an operand directly.  We also
763*e4b17023SJohn Marino      go through a temporary register if it holds a floating point
764*e4b17023SJohn Marino      value.  This gives us better code on systems which can't move
765*e4b17023SJohn Marino      data easily between integer and floating point registers.  */
766*e4b17023SJohn Marino 
767*e4b17023SJohn Marino   dest_mode = orig_mode;
768*e4b17023SJohn Marino   pushing = push_operand (dest, dest_mode);
769*e4b17023SJohn Marino   if (!can_decompose_p (dest)
770*e4b17023SJohn Marino       || (side_effects_p (dest) && !pushing)
771*e4b17023SJohn Marino       || (!SCALAR_INT_MODE_P (dest_mode)
772*e4b17023SJohn Marino 	  && !resolve_reg_p (dest)
773*e4b17023SJohn Marino 	  && !resolve_subreg_p (dest)))
774*e4b17023SJohn Marino     {
775*e4b17023SJohn Marino       if (real_dest == NULL_RTX)
776*e4b17023SJohn Marino 	real_dest = dest;
777*e4b17023SJohn Marino       if (!SCALAR_INT_MODE_P (dest_mode))
778*e4b17023SJohn Marino 	{
779*e4b17023SJohn Marino 	  dest_mode = mode_for_size (GET_MODE_SIZE (dest_mode) * BITS_PER_UNIT,
780*e4b17023SJohn Marino 				     MODE_INT, 0);
781*e4b17023SJohn Marino 	  gcc_assert (dest_mode != BLKmode);
782*e4b17023SJohn Marino 	}
783*e4b17023SJohn Marino       dest = gen_reg_rtx (dest_mode);
784*e4b17023SJohn Marino       if (REG_P (real_dest))
785*e4b17023SJohn Marino 	REG_ATTRS (dest) = REG_ATTRS (real_dest);
786*e4b17023SJohn Marino     }
787*e4b17023SJohn Marino 
788*e4b17023SJohn Marino   if (pushing)
789*e4b17023SJohn Marino     {
790*e4b17023SJohn Marino       unsigned int i, j, jinc;
791*e4b17023SJohn Marino 
792*e4b17023SJohn Marino       gcc_assert (GET_MODE_SIZE (orig_mode) % UNITS_PER_WORD == 0);
793*e4b17023SJohn Marino       gcc_assert (GET_CODE (XEXP (dest, 0)) != PRE_MODIFY);
794*e4b17023SJohn Marino       gcc_assert (GET_CODE (XEXP (dest, 0)) != POST_MODIFY);
795*e4b17023SJohn Marino 
796*e4b17023SJohn Marino       if (WORDS_BIG_ENDIAN == STACK_GROWS_DOWNWARD)
797*e4b17023SJohn Marino 	{
798*e4b17023SJohn Marino 	  j = 0;
799*e4b17023SJohn Marino 	  jinc = 1;
800*e4b17023SJohn Marino 	}
801*e4b17023SJohn Marino       else
802*e4b17023SJohn Marino 	{
803*e4b17023SJohn Marino 	  j = words - 1;
804*e4b17023SJohn Marino 	  jinc = -1;
805*e4b17023SJohn Marino 	}
806*e4b17023SJohn Marino 
807*e4b17023SJohn Marino       for (i = 0; i < words; ++i, j += jinc)
808*e4b17023SJohn Marino 	{
809*e4b17023SJohn Marino 	  rtx temp;
810*e4b17023SJohn Marino 
811*e4b17023SJohn Marino 	  temp = copy_rtx (XEXP (dest, 0));
812*e4b17023SJohn Marino 	  temp = adjust_automodify_address_nv (dest, word_mode, temp,
813*e4b17023SJohn Marino 					       j * UNITS_PER_WORD);
814*e4b17023SJohn Marino 	  emit_move_insn (temp,
815*e4b17023SJohn Marino 			  simplify_gen_subreg_concatn (word_mode, src,
816*e4b17023SJohn Marino 						       orig_mode,
817*e4b17023SJohn Marino 						       j * UNITS_PER_WORD));
818*e4b17023SJohn Marino 	}
819*e4b17023SJohn Marino     }
820*e4b17023SJohn Marino   else
821*e4b17023SJohn Marino     {
822*e4b17023SJohn Marino       unsigned int i;
823*e4b17023SJohn Marino 
824*e4b17023SJohn Marino       if (REG_P (dest) && !HARD_REGISTER_NUM_P (REGNO (dest)))
825*e4b17023SJohn Marino 	emit_clobber (dest);
826*e4b17023SJohn Marino 
827*e4b17023SJohn Marino       for (i = 0; i < words; ++i)
828*e4b17023SJohn Marino 	emit_move_insn (simplify_gen_subreg_concatn (word_mode, dest,
829*e4b17023SJohn Marino 						     dest_mode,
830*e4b17023SJohn Marino 						     i * UNITS_PER_WORD),
831*e4b17023SJohn Marino 			simplify_gen_subreg_concatn (word_mode, src,
832*e4b17023SJohn Marino 						     orig_mode,
833*e4b17023SJohn Marino 						     i * UNITS_PER_WORD));
834*e4b17023SJohn Marino     }
835*e4b17023SJohn Marino 
836*e4b17023SJohn Marino   if (real_dest != NULL_RTX)
837*e4b17023SJohn Marino     {
838*e4b17023SJohn Marino       rtx mdest, minsn, smove;
839*e4b17023SJohn Marino 
840*e4b17023SJohn Marino       if (dest_mode == orig_mode)
841*e4b17023SJohn Marino 	mdest = dest;
842*e4b17023SJohn Marino       else
843*e4b17023SJohn Marino 	mdest = simplify_gen_subreg (orig_mode, dest, GET_MODE (dest), 0);
844*e4b17023SJohn Marino       minsn = emit_move_insn (real_dest, mdest);
845*e4b17023SJohn Marino 
846*e4b17023SJohn Marino       smove = single_set (minsn);
847*e4b17023SJohn Marino       gcc_assert (smove != NULL_RTX);
848*e4b17023SJohn Marino 
849*e4b17023SJohn Marino       resolve_simple_move (smove, minsn);
850*e4b17023SJohn Marino     }
851*e4b17023SJohn Marino 
852*e4b17023SJohn Marino   insns = get_insns ();
853*e4b17023SJohn Marino   end_sequence ();
854*e4b17023SJohn Marino 
855*e4b17023SJohn Marino   copy_reg_eh_region_note_forward (insn, insns, NULL_RTX);
856*e4b17023SJohn Marino 
857*e4b17023SJohn Marino   emit_insn_before (insns, insn);
858*e4b17023SJohn Marino 
859*e4b17023SJohn Marino   delete_insn (insn);
860*e4b17023SJohn Marino 
861*e4b17023SJohn Marino   return insns;
862*e4b17023SJohn Marino }
863*e4b17023SJohn Marino 
864*e4b17023SJohn Marino /* Change a CLOBBER of a decomposed register into a CLOBBER of the
865*e4b17023SJohn Marino    component registers.  Return whether we changed something.  */
866*e4b17023SJohn Marino 
867*e4b17023SJohn Marino static bool
resolve_clobber(rtx pat,rtx insn)868*e4b17023SJohn Marino resolve_clobber (rtx pat, rtx insn)
869*e4b17023SJohn Marino {
870*e4b17023SJohn Marino   rtx reg;
871*e4b17023SJohn Marino   enum machine_mode orig_mode;
872*e4b17023SJohn Marino   unsigned int words, i;
873*e4b17023SJohn Marino   int ret;
874*e4b17023SJohn Marino 
875*e4b17023SJohn Marino   reg = XEXP (pat, 0);
876*e4b17023SJohn Marino   if (!resolve_reg_p (reg) && !resolve_subreg_p (reg))
877*e4b17023SJohn Marino     return false;
878*e4b17023SJohn Marino 
879*e4b17023SJohn Marino   orig_mode = GET_MODE (reg);
880*e4b17023SJohn Marino   words = GET_MODE_SIZE (orig_mode);
881*e4b17023SJohn Marino   words = (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
882*e4b17023SJohn Marino 
883*e4b17023SJohn Marino   ret = validate_change (NULL_RTX, &XEXP (pat, 0),
884*e4b17023SJohn Marino 			 simplify_gen_subreg_concatn (word_mode, reg,
885*e4b17023SJohn Marino 						      orig_mode, 0),
886*e4b17023SJohn Marino 			 0);
887*e4b17023SJohn Marino   df_insn_rescan (insn);
888*e4b17023SJohn Marino   gcc_assert (ret != 0);
889*e4b17023SJohn Marino 
890*e4b17023SJohn Marino   for (i = words - 1; i > 0; --i)
891*e4b17023SJohn Marino     {
892*e4b17023SJohn Marino       rtx x;
893*e4b17023SJohn Marino 
894*e4b17023SJohn Marino       x = simplify_gen_subreg_concatn (word_mode, reg, orig_mode,
895*e4b17023SJohn Marino 				       i * UNITS_PER_WORD);
896*e4b17023SJohn Marino       x = gen_rtx_CLOBBER (VOIDmode, x);
897*e4b17023SJohn Marino       emit_insn_after (x, insn);
898*e4b17023SJohn Marino     }
899*e4b17023SJohn Marino 
900*e4b17023SJohn Marino   resolve_reg_notes (insn);
901*e4b17023SJohn Marino 
902*e4b17023SJohn Marino   return true;
903*e4b17023SJohn Marino }
904*e4b17023SJohn Marino 
905*e4b17023SJohn Marino /* A USE of a decomposed register is no longer meaningful.  Return
906*e4b17023SJohn Marino    whether we changed something.  */
907*e4b17023SJohn Marino 
908*e4b17023SJohn Marino static bool
resolve_use(rtx pat,rtx insn)909*e4b17023SJohn Marino resolve_use (rtx pat, rtx insn)
910*e4b17023SJohn Marino {
911*e4b17023SJohn Marino   if (resolve_reg_p (XEXP (pat, 0)) || resolve_subreg_p (XEXP (pat, 0)))
912*e4b17023SJohn Marino     {
913*e4b17023SJohn Marino       delete_insn (insn);
914*e4b17023SJohn Marino       return true;
915*e4b17023SJohn Marino     }
916*e4b17023SJohn Marino 
917*e4b17023SJohn Marino   resolve_reg_notes (insn);
918*e4b17023SJohn Marino 
919*e4b17023SJohn Marino   return false;
920*e4b17023SJohn Marino }
921*e4b17023SJohn Marino 
922*e4b17023SJohn Marino /* A VAR_LOCATION can be simplified.  */
923*e4b17023SJohn Marino 
924*e4b17023SJohn Marino static void
resolve_debug(rtx insn)925*e4b17023SJohn Marino resolve_debug (rtx insn)
926*e4b17023SJohn Marino {
927*e4b17023SJohn Marino   for_each_rtx (&PATTERN (insn), adjust_decomposed_uses, NULL_RTX);
928*e4b17023SJohn Marino 
929*e4b17023SJohn Marino   df_insn_rescan (insn);
930*e4b17023SJohn Marino 
931*e4b17023SJohn Marino   resolve_reg_notes (insn);
932*e4b17023SJohn Marino }
933*e4b17023SJohn Marino 
934*e4b17023SJohn Marino /* Checks if INSN is a decomposable multiword-shift or zero-extend and
935*e4b17023SJohn Marino    sets the decomposable_context bitmap accordingly.  A non-zero value
936*e4b17023SJohn Marino    is returned if a decomposable insn has been found.  */
937*e4b17023SJohn Marino 
938*e4b17023SJohn Marino static int
find_decomposable_shift_zext(rtx insn)939*e4b17023SJohn Marino find_decomposable_shift_zext (rtx insn)
940*e4b17023SJohn Marino {
941*e4b17023SJohn Marino   rtx set;
942*e4b17023SJohn Marino   rtx op;
943*e4b17023SJohn Marino   rtx op_operand;
944*e4b17023SJohn Marino 
945*e4b17023SJohn Marino   set = single_set (insn);
946*e4b17023SJohn Marino   if (!set)
947*e4b17023SJohn Marino     return 0;
948*e4b17023SJohn Marino 
949*e4b17023SJohn Marino   op = SET_SRC (set);
950*e4b17023SJohn Marino   if (GET_CODE (op) != ASHIFT
951*e4b17023SJohn Marino       && GET_CODE (op) != LSHIFTRT
952*e4b17023SJohn Marino       && GET_CODE (op) != ZERO_EXTEND)
953*e4b17023SJohn Marino     return 0;
954*e4b17023SJohn Marino 
955*e4b17023SJohn Marino   op_operand = XEXP (op, 0);
956*e4b17023SJohn Marino   if (!REG_P (SET_DEST (set)) || !REG_P (op_operand)
957*e4b17023SJohn Marino       || HARD_REGISTER_NUM_P (REGNO (SET_DEST (set)))
958*e4b17023SJohn Marino       || HARD_REGISTER_NUM_P (REGNO (op_operand))
959*e4b17023SJohn Marino       || !SCALAR_INT_MODE_P (GET_MODE (op)))
960*e4b17023SJohn Marino     return 0;
961*e4b17023SJohn Marino 
962*e4b17023SJohn Marino   if (GET_CODE (op) == ZERO_EXTEND)
963*e4b17023SJohn Marino     {
964*e4b17023SJohn Marino       if (GET_MODE (op_operand) != word_mode
965*e4b17023SJohn Marino 	  || GET_MODE_BITSIZE (GET_MODE (op)) != 2 * BITS_PER_WORD)
966*e4b17023SJohn Marino 	return 0;
967*e4b17023SJohn Marino     }
968*e4b17023SJohn Marino   else /* left or right shift */
969*e4b17023SJohn Marino     {
970*e4b17023SJohn Marino       if (!CONST_INT_P (XEXP (op, 1))
971*e4b17023SJohn Marino 	  || INTVAL (XEXP (op, 1)) < BITS_PER_WORD
972*e4b17023SJohn Marino 	  || GET_MODE_BITSIZE (GET_MODE (op_operand)) != 2 * BITS_PER_WORD)
973*e4b17023SJohn Marino 	return 0;
974*e4b17023SJohn Marino     }
975*e4b17023SJohn Marino 
976*e4b17023SJohn Marino   bitmap_set_bit (decomposable_context, REGNO (SET_DEST (set)));
977*e4b17023SJohn Marino 
978*e4b17023SJohn Marino   if (GET_CODE (op) != ZERO_EXTEND)
979*e4b17023SJohn Marino     bitmap_set_bit (decomposable_context, REGNO (op_operand));
980*e4b17023SJohn Marino 
981*e4b17023SJohn Marino   return 1;
982*e4b17023SJohn Marino }
983*e4b17023SJohn Marino 
984*e4b17023SJohn Marino /* Decompose a more than word wide shift (in INSN) of a multiword
985*e4b17023SJohn Marino    pseudo or a multiword zero-extend of a wordmode pseudo into a move
986*e4b17023SJohn Marino    and 'set to zero' insn.  Return a pointer to the new insn when a
987*e4b17023SJohn Marino    replacement was done.  */
988*e4b17023SJohn Marino 
989*e4b17023SJohn Marino static rtx
resolve_shift_zext(rtx insn)990*e4b17023SJohn Marino resolve_shift_zext (rtx insn)
991*e4b17023SJohn Marino {
992*e4b17023SJohn Marino   rtx set;
993*e4b17023SJohn Marino   rtx op;
994*e4b17023SJohn Marino   rtx op_operand;
995*e4b17023SJohn Marino   rtx insns;
996*e4b17023SJohn Marino   rtx src_reg, dest_reg, dest_zero;
997*e4b17023SJohn Marino   int src_reg_num, dest_reg_num, offset1, offset2, src_offset;
998*e4b17023SJohn Marino 
999*e4b17023SJohn Marino   set = single_set (insn);
1000*e4b17023SJohn Marino   if (!set)
1001*e4b17023SJohn Marino     return NULL_RTX;
1002*e4b17023SJohn Marino 
1003*e4b17023SJohn Marino   op = SET_SRC (set);
1004*e4b17023SJohn Marino   if (GET_CODE (op) != ASHIFT
1005*e4b17023SJohn Marino       && GET_CODE (op) != LSHIFTRT
1006*e4b17023SJohn Marino       && GET_CODE (op) != ZERO_EXTEND)
1007*e4b17023SJohn Marino     return NULL_RTX;
1008*e4b17023SJohn Marino 
1009*e4b17023SJohn Marino   op_operand = XEXP (op, 0);
1010*e4b17023SJohn Marino 
1011*e4b17023SJohn Marino   if (!resolve_reg_p (SET_DEST (set)) && !resolve_reg_p (op_operand))
1012*e4b17023SJohn Marino     return NULL_RTX;
1013*e4b17023SJohn Marino 
1014*e4b17023SJohn Marino   /* src_reg_num is the number of the word mode register which we
1015*e4b17023SJohn Marino      are operating on.  For a left shift and a zero_extend on little
1016*e4b17023SJohn Marino      endian machines this is register 0.  */
1017*e4b17023SJohn Marino   src_reg_num = GET_CODE (op) == LSHIFTRT ? 1 : 0;
1018*e4b17023SJohn Marino 
1019*e4b17023SJohn Marino   if (WORDS_BIG_ENDIAN
1020*e4b17023SJohn Marino       && GET_MODE_SIZE (GET_MODE (op_operand)) > UNITS_PER_WORD)
1021*e4b17023SJohn Marino     src_reg_num = 1 - src_reg_num;
1022*e4b17023SJohn Marino 
1023*e4b17023SJohn Marino   if (GET_CODE (op) == ZERO_EXTEND)
1024*e4b17023SJohn Marino     dest_reg_num = WORDS_BIG_ENDIAN ? 1 : 0;
1025*e4b17023SJohn Marino   else
1026*e4b17023SJohn Marino     dest_reg_num = 1 - src_reg_num;
1027*e4b17023SJohn Marino 
1028*e4b17023SJohn Marino   offset1 = UNITS_PER_WORD * dest_reg_num;
1029*e4b17023SJohn Marino   offset2 = UNITS_PER_WORD * (1 - dest_reg_num);
1030*e4b17023SJohn Marino   src_offset = UNITS_PER_WORD * src_reg_num;
1031*e4b17023SJohn Marino 
1032*e4b17023SJohn Marino   start_sequence ();
1033*e4b17023SJohn Marino 
1034*e4b17023SJohn Marino   dest_reg = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
1035*e4b17023SJohn Marino                                           GET_MODE (SET_DEST (set)),
1036*e4b17023SJohn Marino                                           offset1);
1037*e4b17023SJohn Marino   dest_zero = simplify_gen_subreg_concatn (word_mode, SET_DEST (set),
1038*e4b17023SJohn Marino                                            GET_MODE (SET_DEST (set)),
1039*e4b17023SJohn Marino                                            offset2);
1040*e4b17023SJohn Marino   src_reg = simplify_gen_subreg_concatn (word_mode, op_operand,
1041*e4b17023SJohn Marino                                          GET_MODE (op_operand),
1042*e4b17023SJohn Marino                                          src_offset);
1043*e4b17023SJohn Marino   if (GET_CODE (op) != ZERO_EXTEND)
1044*e4b17023SJohn Marino     {
1045*e4b17023SJohn Marino       int shift_count = INTVAL (XEXP (op, 1));
1046*e4b17023SJohn Marino       if (shift_count > BITS_PER_WORD)
1047*e4b17023SJohn Marino 	src_reg = expand_shift (GET_CODE (op) == ASHIFT ?
1048*e4b17023SJohn Marino 				LSHIFT_EXPR : RSHIFT_EXPR,
1049*e4b17023SJohn Marino 				word_mode, src_reg,
1050*e4b17023SJohn Marino 				shift_count - BITS_PER_WORD,
1051*e4b17023SJohn Marino 				dest_reg, 1);
1052*e4b17023SJohn Marino     }
1053*e4b17023SJohn Marino 
1054*e4b17023SJohn Marino   if (dest_reg != src_reg)
1055*e4b17023SJohn Marino     emit_move_insn (dest_reg, src_reg);
1056*e4b17023SJohn Marino   emit_move_insn (dest_zero, CONST0_RTX (word_mode));
1057*e4b17023SJohn Marino   insns = get_insns ();
1058*e4b17023SJohn Marino 
1059*e4b17023SJohn Marino   end_sequence ();
1060*e4b17023SJohn Marino 
1061*e4b17023SJohn Marino   emit_insn_before (insns, insn);
1062*e4b17023SJohn Marino 
1063*e4b17023SJohn Marino   if (dump_file)
1064*e4b17023SJohn Marino     {
1065*e4b17023SJohn Marino       rtx in;
1066*e4b17023SJohn Marino       fprintf (dump_file, "; Replacing insn: %d with insns: ", INSN_UID (insn));
1067*e4b17023SJohn Marino       for (in = insns; in != insn; in = NEXT_INSN (in))
1068*e4b17023SJohn Marino 	fprintf (dump_file, "%d ", INSN_UID (in));
1069*e4b17023SJohn Marino       fprintf (dump_file, "\n");
1070*e4b17023SJohn Marino     }
1071*e4b17023SJohn Marino 
1072*e4b17023SJohn Marino   delete_insn (insn);
1073*e4b17023SJohn Marino   return insns;
1074*e4b17023SJohn Marino }
1075*e4b17023SJohn Marino 
1076*e4b17023SJohn Marino /* Look for registers which are always accessed via word-sized SUBREGs
1077*e4b17023SJohn Marino    or via copies.  Decompose these registers into several word-sized
1078*e4b17023SJohn Marino    pseudo-registers.  */
1079*e4b17023SJohn Marino 
1080*e4b17023SJohn Marino static void
decompose_multiword_subregs(void)1081*e4b17023SJohn Marino decompose_multiword_subregs (void)
1082*e4b17023SJohn Marino {
1083*e4b17023SJohn Marino   unsigned int max;
1084*e4b17023SJohn Marino   basic_block bb;
1085*e4b17023SJohn Marino 
1086*e4b17023SJohn Marino   if (df)
1087*e4b17023SJohn Marino     df_set_flags (DF_DEFER_INSN_RESCAN);
1088*e4b17023SJohn Marino 
1089*e4b17023SJohn Marino   max = max_reg_num ();
1090*e4b17023SJohn Marino 
1091*e4b17023SJohn Marino   /* First see if there are any multi-word pseudo-registers.  If there
1092*e4b17023SJohn Marino      aren't, there is nothing we can do.  This should speed up this
1093*e4b17023SJohn Marino      pass in the normal case, since it should be faster than scanning
1094*e4b17023SJohn Marino      all the insns.  */
1095*e4b17023SJohn Marino   {
1096*e4b17023SJohn Marino     unsigned int i;
1097*e4b17023SJohn Marino 
1098*e4b17023SJohn Marino     for (i = FIRST_PSEUDO_REGISTER; i < max; ++i)
1099*e4b17023SJohn Marino       {
1100*e4b17023SJohn Marino 	if (regno_reg_rtx[i] != NULL
1101*e4b17023SJohn Marino 	    && GET_MODE_SIZE (GET_MODE (regno_reg_rtx[i])) > UNITS_PER_WORD)
1102*e4b17023SJohn Marino 	  break;
1103*e4b17023SJohn Marino       }
1104*e4b17023SJohn Marino     if (i == max)
1105*e4b17023SJohn Marino       return;
1106*e4b17023SJohn Marino   }
1107*e4b17023SJohn Marino 
1108*e4b17023SJohn Marino   if (df)
1109*e4b17023SJohn Marino     run_word_dce ();
1110*e4b17023SJohn Marino 
1111*e4b17023SJohn Marino   /* FIXME: When the dataflow branch is merged, we can change this
1112*e4b17023SJohn Marino      code to look for each multi-word pseudo-register and to find each
1113*e4b17023SJohn Marino      insn which sets or uses that register.  That should be faster
1114*e4b17023SJohn Marino      than scanning all the insns.  */
1115*e4b17023SJohn Marino 
1116*e4b17023SJohn Marino   decomposable_context = BITMAP_ALLOC (NULL);
1117*e4b17023SJohn Marino   non_decomposable_context = BITMAP_ALLOC (NULL);
1118*e4b17023SJohn Marino   subreg_context = BITMAP_ALLOC (NULL);
1119*e4b17023SJohn Marino 
1120*e4b17023SJohn Marino   reg_copy_graph = VEC_alloc (bitmap, heap, max);
1121*e4b17023SJohn Marino   VEC_safe_grow (bitmap, heap, reg_copy_graph, max);
1122*e4b17023SJohn Marino   memset (VEC_address (bitmap, reg_copy_graph), 0, sizeof (bitmap) * max);
1123*e4b17023SJohn Marino 
1124*e4b17023SJohn Marino   FOR_EACH_BB (bb)
1125*e4b17023SJohn Marino     {
1126*e4b17023SJohn Marino       rtx insn;
1127*e4b17023SJohn Marino 
1128*e4b17023SJohn Marino       FOR_BB_INSNS (bb, insn)
1129*e4b17023SJohn Marino 	{
1130*e4b17023SJohn Marino 	  rtx set;
1131*e4b17023SJohn Marino 	  enum classify_move_insn cmi;
1132*e4b17023SJohn Marino 	  int i, n;
1133*e4b17023SJohn Marino 
1134*e4b17023SJohn Marino 	  if (!INSN_P (insn)
1135*e4b17023SJohn Marino 	      || GET_CODE (PATTERN (insn)) == CLOBBER
1136*e4b17023SJohn Marino 	      || GET_CODE (PATTERN (insn)) == USE)
1137*e4b17023SJohn Marino 	    continue;
1138*e4b17023SJohn Marino 
1139*e4b17023SJohn Marino 	  recog_memoized (insn);
1140*e4b17023SJohn Marino 
1141*e4b17023SJohn Marino 	  if (find_decomposable_shift_zext (insn))
1142*e4b17023SJohn Marino 	    continue;
1143*e4b17023SJohn Marino 
1144*e4b17023SJohn Marino 	  extract_insn (insn);
1145*e4b17023SJohn Marino 
1146*e4b17023SJohn Marino 	  set = simple_move (insn);
1147*e4b17023SJohn Marino 
1148*e4b17023SJohn Marino 	  if (!set)
1149*e4b17023SJohn Marino 	    cmi = NOT_SIMPLE_MOVE;
1150*e4b17023SJohn Marino 	  else
1151*e4b17023SJohn Marino 	    {
1152*e4b17023SJohn Marino 	      if (find_pseudo_copy (set))
1153*e4b17023SJohn Marino 		cmi = SIMPLE_PSEUDO_REG_MOVE;
1154*e4b17023SJohn Marino 	      else
1155*e4b17023SJohn Marino 		cmi = SIMPLE_MOVE;
1156*e4b17023SJohn Marino 	    }
1157*e4b17023SJohn Marino 
1158*e4b17023SJohn Marino 	  n = recog_data.n_operands;
1159*e4b17023SJohn Marino 	  for (i = 0; i < n; ++i)
1160*e4b17023SJohn Marino 	    {
1161*e4b17023SJohn Marino 	      for_each_rtx (&recog_data.operand[i],
1162*e4b17023SJohn Marino 			    find_decomposable_subregs,
1163*e4b17023SJohn Marino 			    &cmi);
1164*e4b17023SJohn Marino 
1165*e4b17023SJohn Marino 	      /* We handle ASM_OPERANDS as a special case to support
1166*e4b17023SJohn Marino 		 things like x86 rdtsc which returns a DImode value.
1167*e4b17023SJohn Marino 		 We can decompose the output, which will certainly be
1168*e4b17023SJohn Marino 		 operand 0, but not the inputs.  */
1169*e4b17023SJohn Marino 
1170*e4b17023SJohn Marino 	      if (cmi == SIMPLE_MOVE
1171*e4b17023SJohn Marino 		  && GET_CODE (SET_SRC (set)) == ASM_OPERANDS)
1172*e4b17023SJohn Marino 		{
1173*e4b17023SJohn Marino 		  gcc_assert (i == 0);
1174*e4b17023SJohn Marino 		  cmi = NOT_SIMPLE_MOVE;
1175*e4b17023SJohn Marino 		}
1176*e4b17023SJohn Marino 	    }
1177*e4b17023SJohn Marino 	}
1178*e4b17023SJohn Marino     }
1179*e4b17023SJohn Marino 
1180*e4b17023SJohn Marino   bitmap_and_compl_into (decomposable_context, non_decomposable_context);
1181*e4b17023SJohn Marino   if (!bitmap_empty_p (decomposable_context))
1182*e4b17023SJohn Marino     {
1183*e4b17023SJohn Marino       sbitmap sub_blocks;
1184*e4b17023SJohn Marino       unsigned int i;
1185*e4b17023SJohn Marino       sbitmap_iterator sbi;
1186*e4b17023SJohn Marino       bitmap_iterator iter;
1187*e4b17023SJohn Marino       unsigned int regno;
1188*e4b17023SJohn Marino 
1189*e4b17023SJohn Marino       propagate_pseudo_copies ();
1190*e4b17023SJohn Marino 
1191*e4b17023SJohn Marino       sub_blocks = sbitmap_alloc (last_basic_block);
1192*e4b17023SJohn Marino       sbitmap_zero (sub_blocks);
1193*e4b17023SJohn Marino 
1194*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_BITMAP (decomposable_context, 0, regno, iter)
1195*e4b17023SJohn Marino 	decompose_register (regno);
1196*e4b17023SJohn Marino 
1197*e4b17023SJohn Marino       FOR_EACH_BB (bb)
1198*e4b17023SJohn Marino 	{
1199*e4b17023SJohn Marino 	  rtx insn;
1200*e4b17023SJohn Marino 
1201*e4b17023SJohn Marino 	  FOR_BB_INSNS (bb, insn)
1202*e4b17023SJohn Marino 	    {
1203*e4b17023SJohn Marino 	      rtx pat;
1204*e4b17023SJohn Marino 
1205*e4b17023SJohn Marino 	      if (!INSN_P (insn))
1206*e4b17023SJohn Marino 		continue;
1207*e4b17023SJohn Marino 
1208*e4b17023SJohn Marino 	      pat = PATTERN (insn);
1209*e4b17023SJohn Marino 	      if (GET_CODE (pat) == CLOBBER)
1210*e4b17023SJohn Marino 		resolve_clobber (pat, insn);
1211*e4b17023SJohn Marino 	      else if (GET_CODE (pat) == USE)
1212*e4b17023SJohn Marino 		resolve_use (pat, insn);
1213*e4b17023SJohn Marino 	      else if (DEBUG_INSN_P (insn))
1214*e4b17023SJohn Marino 		resolve_debug (insn);
1215*e4b17023SJohn Marino 	      else
1216*e4b17023SJohn Marino 		{
1217*e4b17023SJohn Marino 		  rtx set;
1218*e4b17023SJohn Marino 		  int i;
1219*e4b17023SJohn Marino 
1220*e4b17023SJohn Marino 		  recog_memoized (insn);
1221*e4b17023SJohn Marino 		  extract_insn (insn);
1222*e4b17023SJohn Marino 
1223*e4b17023SJohn Marino 		  set = simple_move (insn);
1224*e4b17023SJohn Marino 		  if (set)
1225*e4b17023SJohn Marino 		    {
1226*e4b17023SJohn Marino 		      rtx orig_insn = insn;
1227*e4b17023SJohn Marino 		      bool cfi = control_flow_insn_p (insn);
1228*e4b17023SJohn Marino 
1229*e4b17023SJohn Marino 		      /* We can end up splitting loads to multi-word pseudos
1230*e4b17023SJohn Marino 			 into separate loads to machine word size pseudos.
1231*e4b17023SJohn Marino 			 When this happens, we first had one load that can
1232*e4b17023SJohn Marino 			 throw, and after resolve_simple_move we'll have a
1233*e4b17023SJohn Marino 			 bunch of loads (at least two).  All those loads may
1234*e4b17023SJohn Marino 			 trap if we can have non-call exceptions, so they
1235*e4b17023SJohn Marino 			 all will end the current basic block.  We split the
1236*e4b17023SJohn Marino 			 block after the outer loop over all insns, but we
1237*e4b17023SJohn Marino 			 make sure here that we will be able to split the
1238*e4b17023SJohn Marino 			 basic block and still produce the correct control
1239*e4b17023SJohn Marino 			 flow graph for it.  */
1240*e4b17023SJohn Marino 		      gcc_assert (!cfi
1241*e4b17023SJohn Marino 				  || (cfun->can_throw_non_call_exceptions
1242*e4b17023SJohn Marino 				      && can_throw_internal (insn)));
1243*e4b17023SJohn Marino 
1244*e4b17023SJohn Marino 		      insn = resolve_simple_move (set, insn);
1245*e4b17023SJohn Marino 		      if (insn != orig_insn)
1246*e4b17023SJohn Marino 			{
1247*e4b17023SJohn Marino 			  recog_memoized (insn);
1248*e4b17023SJohn Marino 			  extract_insn (insn);
1249*e4b17023SJohn Marino 
1250*e4b17023SJohn Marino 			  if (cfi)
1251*e4b17023SJohn Marino 			    SET_BIT (sub_blocks, bb->index);
1252*e4b17023SJohn Marino 			}
1253*e4b17023SJohn Marino 		    }
1254*e4b17023SJohn Marino 		  else
1255*e4b17023SJohn Marino 		    {
1256*e4b17023SJohn Marino 		      rtx decomposed_shift;
1257*e4b17023SJohn Marino 
1258*e4b17023SJohn Marino 		      decomposed_shift = resolve_shift_zext (insn);
1259*e4b17023SJohn Marino 		      if (decomposed_shift != NULL_RTX)
1260*e4b17023SJohn Marino 			{
1261*e4b17023SJohn Marino 			  insn = decomposed_shift;
1262*e4b17023SJohn Marino 			  recog_memoized (insn);
1263*e4b17023SJohn Marino 			  extract_insn (insn);
1264*e4b17023SJohn Marino 			}
1265*e4b17023SJohn Marino 		    }
1266*e4b17023SJohn Marino 
1267*e4b17023SJohn Marino 		  for (i = recog_data.n_operands - 1; i >= 0; --i)
1268*e4b17023SJohn Marino 		    for_each_rtx (recog_data.operand_loc[i],
1269*e4b17023SJohn Marino 				  resolve_subreg_use,
1270*e4b17023SJohn Marino 				  insn);
1271*e4b17023SJohn Marino 
1272*e4b17023SJohn Marino 		  resolve_reg_notes (insn);
1273*e4b17023SJohn Marino 
1274*e4b17023SJohn Marino 		  if (num_validated_changes () > 0)
1275*e4b17023SJohn Marino 		    {
1276*e4b17023SJohn Marino 		      for (i = recog_data.n_dups - 1; i >= 0; --i)
1277*e4b17023SJohn Marino 			{
1278*e4b17023SJohn Marino 			  rtx *pl = recog_data.dup_loc[i];
1279*e4b17023SJohn Marino 			  int dup_num = recog_data.dup_num[i];
1280*e4b17023SJohn Marino 			  rtx *px = recog_data.operand_loc[dup_num];
1281*e4b17023SJohn Marino 
1282*e4b17023SJohn Marino 			  validate_unshare_change (insn, pl, *px, 1);
1283*e4b17023SJohn Marino 			}
1284*e4b17023SJohn Marino 
1285*e4b17023SJohn Marino 		      i = apply_change_group ();
1286*e4b17023SJohn Marino 		      gcc_assert (i);
1287*e4b17023SJohn Marino 		    }
1288*e4b17023SJohn Marino 		}
1289*e4b17023SJohn Marino 	    }
1290*e4b17023SJohn Marino 	}
1291*e4b17023SJohn Marino 
1292*e4b17023SJohn Marino       /* If we had insns to split that caused control flow insns in the middle
1293*e4b17023SJohn Marino 	 of a basic block, split those blocks now.  Note that we only handle
1294*e4b17023SJohn Marino 	 the case where splitting a load has caused multiple possibly trapping
1295*e4b17023SJohn Marino 	 loads to appear.  */
1296*e4b17023SJohn Marino       EXECUTE_IF_SET_IN_SBITMAP (sub_blocks, 0, i, sbi)
1297*e4b17023SJohn Marino 	{
1298*e4b17023SJohn Marino 	  rtx insn, end;
1299*e4b17023SJohn Marino 	  edge fallthru;
1300*e4b17023SJohn Marino 
1301*e4b17023SJohn Marino 	  bb = BASIC_BLOCK (i);
1302*e4b17023SJohn Marino 	  insn = BB_HEAD (bb);
1303*e4b17023SJohn Marino 	  end = BB_END (bb);
1304*e4b17023SJohn Marino 
1305*e4b17023SJohn Marino 	  while (insn != end)
1306*e4b17023SJohn Marino 	    {
1307*e4b17023SJohn Marino 	      if (control_flow_insn_p (insn))
1308*e4b17023SJohn Marino 		{
1309*e4b17023SJohn Marino 		  /* Split the block after insn.  There will be a fallthru
1310*e4b17023SJohn Marino 		     edge, which is OK so we keep it.  We have to create the
1311*e4b17023SJohn Marino 		     exception edges ourselves.  */
1312*e4b17023SJohn Marino 		  fallthru = split_block (bb, insn);
1313*e4b17023SJohn Marino 		  rtl_make_eh_edge (NULL, bb, BB_END (bb));
1314*e4b17023SJohn Marino 		  bb = fallthru->dest;
1315*e4b17023SJohn Marino 		  insn = BB_HEAD (bb);
1316*e4b17023SJohn Marino 		}
1317*e4b17023SJohn Marino 	      else
1318*e4b17023SJohn Marino 	        insn = NEXT_INSN (insn);
1319*e4b17023SJohn Marino 	    }
1320*e4b17023SJohn Marino 	}
1321*e4b17023SJohn Marino 
1322*e4b17023SJohn Marino       sbitmap_free (sub_blocks);
1323*e4b17023SJohn Marino     }
1324*e4b17023SJohn Marino 
1325*e4b17023SJohn Marino   {
1326*e4b17023SJohn Marino     unsigned int i;
1327*e4b17023SJohn Marino     bitmap b;
1328*e4b17023SJohn Marino 
1329*e4b17023SJohn Marino     FOR_EACH_VEC_ELT (bitmap, reg_copy_graph, i, b)
1330*e4b17023SJohn Marino       if (b)
1331*e4b17023SJohn Marino 	BITMAP_FREE (b);
1332*e4b17023SJohn Marino   }
1333*e4b17023SJohn Marino 
1334*e4b17023SJohn Marino   VEC_free (bitmap, heap, reg_copy_graph);
1335*e4b17023SJohn Marino 
1336*e4b17023SJohn Marino   BITMAP_FREE (decomposable_context);
1337*e4b17023SJohn Marino   BITMAP_FREE (non_decomposable_context);
1338*e4b17023SJohn Marino   BITMAP_FREE (subreg_context);
1339*e4b17023SJohn Marino }
1340*e4b17023SJohn Marino 
1341*e4b17023SJohn Marino /* Gate function for lower subreg pass.  */
1342*e4b17023SJohn Marino 
1343*e4b17023SJohn Marino static bool
gate_handle_lower_subreg(void)1344*e4b17023SJohn Marino gate_handle_lower_subreg (void)
1345*e4b17023SJohn Marino {
1346*e4b17023SJohn Marino   return flag_split_wide_types != 0;
1347*e4b17023SJohn Marino }
1348*e4b17023SJohn Marino 
1349*e4b17023SJohn Marino /* Implement first lower subreg pass.  */
1350*e4b17023SJohn Marino 
1351*e4b17023SJohn Marino static unsigned int
rest_of_handle_lower_subreg(void)1352*e4b17023SJohn Marino rest_of_handle_lower_subreg (void)
1353*e4b17023SJohn Marino {
1354*e4b17023SJohn Marino   decompose_multiword_subregs ();
1355*e4b17023SJohn Marino   return 0;
1356*e4b17023SJohn Marino }
1357*e4b17023SJohn Marino 
1358*e4b17023SJohn Marino /* Implement second lower subreg pass.  */
1359*e4b17023SJohn Marino 
1360*e4b17023SJohn Marino static unsigned int
rest_of_handle_lower_subreg2(void)1361*e4b17023SJohn Marino rest_of_handle_lower_subreg2 (void)
1362*e4b17023SJohn Marino {
1363*e4b17023SJohn Marino   decompose_multiword_subregs ();
1364*e4b17023SJohn Marino   return 0;
1365*e4b17023SJohn Marino }
1366*e4b17023SJohn Marino 
1367*e4b17023SJohn Marino struct rtl_opt_pass pass_lower_subreg =
1368*e4b17023SJohn Marino {
1369*e4b17023SJohn Marino  {
1370*e4b17023SJohn Marino   RTL_PASS,
1371*e4b17023SJohn Marino   "subreg1",	                        /* name */
1372*e4b17023SJohn Marino   gate_handle_lower_subreg,             /* gate */
1373*e4b17023SJohn Marino   rest_of_handle_lower_subreg,          /* execute */
1374*e4b17023SJohn Marino   NULL,                                 /* sub */
1375*e4b17023SJohn Marino   NULL,                                 /* next */
1376*e4b17023SJohn Marino   0,                                    /* static_pass_number */
1377*e4b17023SJohn Marino   TV_LOWER_SUBREG,                      /* tv_id */
1378*e4b17023SJohn Marino   0,                                    /* properties_required */
1379*e4b17023SJohn Marino   0,                                    /* properties_provided */
1380*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
1381*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
1382*e4b17023SJohn Marino   TODO_ggc_collect |
1383*e4b17023SJohn Marino   TODO_verify_flow                      /* todo_flags_finish */
1384*e4b17023SJohn Marino  }
1385*e4b17023SJohn Marino };
1386*e4b17023SJohn Marino 
1387*e4b17023SJohn Marino struct rtl_opt_pass pass_lower_subreg2 =
1388*e4b17023SJohn Marino {
1389*e4b17023SJohn Marino  {
1390*e4b17023SJohn Marino   RTL_PASS,
1391*e4b17023SJohn Marino   "subreg2",	                        /* name */
1392*e4b17023SJohn Marino   gate_handle_lower_subreg,             /* gate */
1393*e4b17023SJohn Marino   rest_of_handle_lower_subreg2,          /* execute */
1394*e4b17023SJohn Marino   NULL,                                 /* sub */
1395*e4b17023SJohn Marino   NULL,                                 /* next */
1396*e4b17023SJohn Marino   0,                                    /* static_pass_number */
1397*e4b17023SJohn Marino   TV_LOWER_SUBREG,                      /* tv_id */
1398*e4b17023SJohn Marino   0,                                    /* properties_required */
1399*e4b17023SJohn Marino   0,                                    /* properties_provided */
1400*e4b17023SJohn Marino   0,                                    /* properties_destroyed */
1401*e4b17023SJohn Marino   0,                                    /* todo_flags_start */
1402*e4b17023SJohn Marino   TODO_df_finish | TODO_verify_rtl_sharing |
1403*e4b17023SJohn Marino   TODO_ggc_collect |
1404*e4b17023SJohn Marino   TODO_verify_flow                      /* todo_flags_finish */
1405*e4b17023SJohn Marino  }
1406*e4b17023SJohn Marino };
1407