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 = ®_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