annotate gcc/lra.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* LRA (local register allocator) driver and LRA utilities.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2010-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Vladimir Makarov <vmakarov@redhat.com>.
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 /* The Local Register Allocator (LRA) is a replacement of former
kono
parents:
diff changeset
23 reload pass. It is focused to simplify code solving the reload
kono
parents:
diff changeset
24 pass tasks, to make the code maintenance easier, and to implement new
kono
parents:
diff changeset
25 perspective optimizations.
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 The major LRA design solutions are:
kono
parents:
diff changeset
28 o division small manageable, separated sub-tasks
kono
parents:
diff changeset
29 o reflection of all transformations and decisions in RTL as more
kono
parents:
diff changeset
30 as possible
kono
parents:
diff changeset
31 o insn constraints as a primary source of the info (minimizing
kono
parents:
diff changeset
32 number of target-depended macros/hooks)
kono
parents:
diff changeset
33
kono
parents:
diff changeset
34 In brief LRA works by iterative insn process with the final goal is
kono
parents:
diff changeset
35 to satisfy all insn and address constraints:
kono
parents:
diff changeset
36 o New reload insns (in brief reloads) and reload pseudos might be
kono
parents:
diff changeset
37 generated;
kono
parents:
diff changeset
38 o Some pseudos might be spilled to assign hard registers to
kono
parents:
diff changeset
39 new reload pseudos;
kono
parents:
diff changeset
40 o Recalculating spilled pseudo values (rematerialization);
kono
parents:
diff changeset
41 o Changing spilled pseudos to stack memory or their equivalences;
kono
parents:
diff changeset
42 o Allocation stack memory changes the address displacement and
kono
parents:
diff changeset
43 new iteration is needed.
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 Here is block diagram of LRA passes:
kono
parents:
diff changeset
46
kono
parents:
diff changeset
47 ------------------------
kono
parents:
diff changeset
48 --------------- | Undo inheritance for | ---------------
kono
parents:
diff changeset
49 | Memory-memory | | spilled pseudos, | | New (and old) |
kono
parents:
diff changeset
50 | move coalesce |<---| splits for pseudos got |<-- | pseudos |
kono
parents:
diff changeset
51 --------------- | the same hard regs, | | assignment |
kono
parents:
diff changeset
52 Start | | and optional reloads | ---------------
kono
parents:
diff changeset
53 | | ------------------------ ^
kono
parents:
diff changeset
54 V | ---------------- |
kono
parents:
diff changeset
55 ----------- V | Update virtual | |
kono
parents:
diff changeset
56 | Remove |----> ------------>| register | |
kono
parents:
diff changeset
57 | scratches | ^ | displacements | |
kono
parents:
diff changeset
58 ----------- | ---------------- |
kono
parents:
diff changeset
59 | | |
kono
parents:
diff changeset
60 | V New |
kono
parents:
diff changeset
61 | ------------ pseudos -------------------
kono
parents:
diff changeset
62 | |Constraints:| or insns | Inheritance/split |
kono
parents:
diff changeset
63 | | RTL |--------->| transformations |
kono
parents:
diff changeset
64 | | transfor- | | in EBB scope |
kono
parents:
diff changeset
65 | substi- | mations | -------------------
kono
parents:
diff changeset
66 | tutions ------------
kono
parents:
diff changeset
67 | | No change
kono
parents:
diff changeset
68 ---------------- V
kono
parents:
diff changeset
69 | Spilled pseudo | -------------------
kono
parents:
diff changeset
70 | to memory |<----| Rematerialization |
kono
parents:
diff changeset
71 | substitution | -------------------
kono
parents:
diff changeset
72 ----------------
kono
parents:
diff changeset
73 | No susbtitions
kono
parents:
diff changeset
74 V
kono
parents:
diff changeset
75 -------------------------
kono
parents:
diff changeset
76 | Hard regs substitution, |
kono
parents:
diff changeset
77 | devirtalization, and |------> Finish
kono
parents:
diff changeset
78 | restoring scratches got |
kono
parents:
diff changeset
79 | memory |
kono
parents:
diff changeset
80 -------------------------
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 To speed up the process:
kono
parents:
diff changeset
83 o We process only insns affected by changes on previous
kono
parents:
diff changeset
84 iterations;
kono
parents:
diff changeset
85 o We don't use DFA-infrastructure because it results in much slower
kono
parents:
diff changeset
86 compiler speed than a special IR described below does;
kono
parents:
diff changeset
87 o We use a special insn representation for quick access to insn
kono
parents:
diff changeset
88 info which is always *synchronized* with the current RTL;
kono
parents:
diff changeset
89 o Insn IR is minimized by memory. It is divided on three parts:
kono
parents:
diff changeset
90 o one specific for each insn in RTL (only operand locations);
kono
parents:
diff changeset
91 o one common for all insns in RTL with the same insn code
kono
parents:
diff changeset
92 (different operand attributes from machine descriptions);
kono
parents:
diff changeset
93 o one oriented for maintenance of live info (list of pseudos).
kono
parents:
diff changeset
94 o Pseudo data:
kono
parents:
diff changeset
95 o all insns where the pseudo is referenced;
kono
parents:
diff changeset
96 o live info (conflicting hard regs, live ranges, # of
kono
parents:
diff changeset
97 references etc);
kono
parents:
diff changeset
98 o data used for assigning (preferred hard regs, costs etc).
kono
parents:
diff changeset
99
kono
parents:
diff changeset
100 This file contains LRA driver, LRA utility functions and data, and
kono
parents:
diff changeset
101 code for dealing with scratches. */
kono
parents:
diff changeset
102
kono
parents:
diff changeset
103 #include "config.h"
kono
parents:
diff changeset
104 #include "system.h"
kono
parents:
diff changeset
105 #include "coretypes.h"
kono
parents:
diff changeset
106 #include "backend.h"
kono
parents:
diff changeset
107 #include "target.h"
kono
parents:
diff changeset
108 #include "rtl.h"
kono
parents:
diff changeset
109 #include "tree.h"
kono
parents:
diff changeset
110 #include "predict.h"
kono
parents:
diff changeset
111 #include "df.h"
kono
parents:
diff changeset
112 #include "memmodel.h"
kono
parents:
diff changeset
113 #include "tm_p.h"
kono
parents:
diff changeset
114 #include "optabs.h"
kono
parents:
diff changeset
115 #include "regs.h"
kono
parents:
diff changeset
116 #include "ira.h"
kono
parents:
diff changeset
117 #include "recog.h"
kono
parents:
diff changeset
118 #include "expr.h"
kono
parents:
diff changeset
119 #include "cfgrtl.h"
kono
parents:
diff changeset
120 #include "cfgbuild.h"
kono
parents:
diff changeset
121 #include "lra.h"
kono
parents:
diff changeset
122 #include "lra-int.h"
kono
parents:
diff changeset
123 #include "print-rtl.h"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
124 #include "function-abi.h"
111
kono
parents:
diff changeset
125
kono
parents:
diff changeset
126 /* Dump bitmap SET with TITLE and BB INDEX. */
kono
parents:
diff changeset
127 void
kono
parents:
diff changeset
128 lra_dump_bitmap_with_title (const char *title, bitmap set, int index)
kono
parents:
diff changeset
129 {
kono
parents:
diff changeset
130 unsigned int i;
kono
parents:
diff changeset
131 int count;
kono
parents:
diff changeset
132 bitmap_iterator bi;
kono
parents:
diff changeset
133 static const int max_nums_on_line = 10;
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 if (bitmap_empty_p (set))
kono
parents:
diff changeset
136 return;
kono
parents:
diff changeset
137 fprintf (lra_dump_file, " %s %d:", title, index);
kono
parents:
diff changeset
138 fprintf (lra_dump_file, "\n");
kono
parents:
diff changeset
139 count = max_nums_on_line + 1;
kono
parents:
diff changeset
140 EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
kono
parents:
diff changeset
141 {
kono
parents:
diff changeset
142 if (count > max_nums_on_line)
kono
parents:
diff changeset
143 {
kono
parents:
diff changeset
144 fprintf (lra_dump_file, "\n ");
kono
parents:
diff changeset
145 count = 0;
kono
parents:
diff changeset
146 }
kono
parents:
diff changeset
147 fprintf (lra_dump_file, " %4u", i);
kono
parents:
diff changeset
148 count++;
kono
parents:
diff changeset
149 }
kono
parents:
diff changeset
150 fprintf (lra_dump_file, "\n");
kono
parents:
diff changeset
151 }
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 /* Hard registers currently not available for allocation. It can
kono
parents:
diff changeset
154 changed after some hard registers become not eliminable. */
kono
parents:
diff changeset
155 HARD_REG_SET lra_no_alloc_regs;
kono
parents:
diff changeset
156
kono
parents:
diff changeset
157 static int get_new_reg_value (void);
kono
parents:
diff changeset
158 static void expand_reg_info (void);
kono
parents:
diff changeset
159 static void invalidate_insn_recog_data (int);
kono
parents:
diff changeset
160 static int get_insn_freq (rtx_insn *);
kono
parents:
diff changeset
161 static void invalidate_insn_data_regno_info (lra_insn_recog_data_t,
kono
parents:
diff changeset
162 rtx_insn *, int);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
163 static void remove_scratches_1 (rtx_insn *);
111
kono
parents:
diff changeset
164
kono
parents:
diff changeset
165 /* Expand all regno related info needed for LRA. */
kono
parents:
diff changeset
166 static void
kono
parents:
diff changeset
167 expand_reg_data (int old)
kono
parents:
diff changeset
168 {
kono
parents:
diff changeset
169 resize_reg_info ();
kono
parents:
diff changeset
170 expand_reg_info ();
kono
parents:
diff changeset
171 ira_expand_reg_equiv ();
kono
parents:
diff changeset
172 for (int i = (int) max_reg_num () - 1; i >= old; i--)
kono
parents:
diff changeset
173 lra_change_class (i, ALL_REGS, " Set", true);
kono
parents:
diff changeset
174 }
kono
parents:
diff changeset
175
kono
parents:
diff changeset
176 /* Create and return a new reg of ORIGINAL mode. If ORIGINAL is NULL
kono
parents:
diff changeset
177 or of VOIDmode, use MD_MODE for the new reg. Initialize its
kono
parents:
diff changeset
178 register class to RCLASS. Print message about assigning class
kono
parents:
diff changeset
179 RCLASS containing new register name TITLE unless it is NULL. Use
kono
parents:
diff changeset
180 attributes of ORIGINAL if it is a register. The created register
kono
parents:
diff changeset
181 will have unique held value. */
kono
parents:
diff changeset
182 rtx
kono
parents:
diff changeset
183 lra_create_new_reg_with_unique_value (machine_mode md_mode, rtx original,
kono
parents:
diff changeset
184 enum reg_class rclass, const char *title)
kono
parents:
diff changeset
185 {
kono
parents:
diff changeset
186 machine_mode mode;
kono
parents:
diff changeset
187 rtx new_reg;
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189 if (original == NULL_RTX || (mode = GET_MODE (original)) == VOIDmode)
kono
parents:
diff changeset
190 mode = md_mode;
kono
parents:
diff changeset
191 lra_assert (mode != VOIDmode);
kono
parents:
diff changeset
192 new_reg = gen_reg_rtx (mode);
kono
parents:
diff changeset
193 if (original == NULL_RTX || ! REG_P (original))
kono
parents:
diff changeset
194 {
kono
parents:
diff changeset
195 if (lra_dump_file != NULL)
kono
parents:
diff changeset
196 fprintf (lra_dump_file, " Creating newreg=%i", REGNO (new_reg));
kono
parents:
diff changeset
197 }
kono
parents:
diff changeset
198 else
kono
parents:
diff changeset
199 {
kono
parents:
diff changeset
200 if (ORIGINAL_REGNO (original) >= FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
201 ORIGINAL_REGNO (new_reg) = ORIGINAL_REGNO (original);
kono
parents:
diff changeset
202 REG_USERVAR_P (new_reg) = REG_USERVAR_P (original);
kono
parents:
diff changeset
203 REG_POINTER (new_reg) = REG_POINTER (original);
kono
parents:
diff changeset
204 REG_ATTRS (new_reg) = REG_ATTRS (original);
kono
parents:
diff changeset
205 if (lra_dump_file != NULL)
kono
parents:
diff changeset
206 fprintf (lra_dump_file, " Creating newreg=%i from oldreg=%i",
kono
parents:
diff changeset
207 REGNO (new_reg), REGNO (original));
kono
parents:
diff changeset
208 }
kono
parents:
diff changeset
209 if (lra_dump_file != NULL)
kono
parents:
diff changeset
210 {
kono
parents:
diff changeset
211 if (title != NULL)
kono
parents:
diff changeset
212 fprintf (lra_dump_file, ", assigning class %s to%s%s r%d",
kono
parents:
diff changeset
213 reg_class_names[rclass], *title == '\0' ? "" : " ",
kono
parents:
diff changeset
214 title, REGNO (new_reg));
kono
parents:
diff changeset
215 fprintf (lra_dump_file, "\n");
kono
parents:
diff changeset
216 }
kono
parents:
diff changeset
217 expand_reg_data (max_reg_num ());
kono
parents:
diff changeset
218 setup_reg_classes (REGNO (new_reg), rclass, NO_REGS, rclass);
kono
parents:
diff changeset
219 return new_reg;
kono
parents:
diff changeset
220 }
kono
parents:
diff changeset
221
kono
parents:
diff changeset
222 /* Analogous to the previous function but also inherits value of
kono
parents:
diff changeset
223 ORIGINAL. */
kono
parents:
diff changeset
224 rtx
kono
parents:
diff changeset
225 lra_create_new_reg (machine_mode md_mode, rtx original,
kono
parents:
diff changeset
226 enum reg_class rclass, const char *title)
kono
parents:
diff changeset
227 {
kono
parents:
diff changeset
228 rtx new_reg;
kono
parents:
diff changeset
229
kono
parents:
diff changeset
230 new_reg
kono
parents:
diff changeset
231 = lra_create_new_reg_with_unique_value (md_mode, original, rclass, title);
kono
parents:
diff changeset
232 if (original != NULL_RTX && REG_P (original))
kono
parents:
diff changeset
233 lra_assign_reg_val (REGNO (original), REGNO (new_reg));
kono
parents:
diff changeset
234 return new_reg;
kono
parents:
diff changeset
235 }
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 /* Set up for REGNO unique hold value. */
kono
parents:
diff changeset
238 void
kono
parents:
diff changeset
239 lra_set_regno_unique_value (int regno)
kono
parents:
diff changeset
240 {
kono
parents:
diff changeset
241 lra_reg_info[regno].val = get_new_reg_value ();
kono
parents:
diff changeset
242 }
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 /* Invalidate INSN related info used by LRA. The info should never be
kono
parents:
diff changeset
245 used after that. */
kono
parents:
diff changeset
246 void
kono
parents:
diff changeset
247 lra_invalidate_insn_data (rtx_insn *insn)
kono
parents:
diff changeset
248 {
kono
parents:
diff changeset
249 lra_invalidate_insn_regno_info (insn);
kono
parents:
diff changeset
250 invalidate_insn_recog_data (INSN_UID (insn));
kono
parents:
diff changeset
251 }
kono
parents:
diff changeset
252
kono
parents:
diff changeset
253 /* Mark INSN deleted and invalidate the insn related info used by
kono
parents:
diff changeset
254 LRA. */
kono
parents:
diff changeset
255 void
kono
parents:
diff changeset
256 lra_set_insn_deleted (rtx_insn *insn)
kono
parents:
diff changeset
257 {
kono
parents:
diff changeset
258 lra_invalidate_insn_data (insn);
kono
parents:
diff changeset
259 SET_INSN_DELETED (insn);
kono
parents:
diff changeset
260 }
kono
parents:
diff changeset
261
kono
parents:
diff changeset
262 /* Delete an unneeded INSN and any previous insns who sole purpose is
kono
parents:
diff changeset
263 loading data that is dead in INSN. */
kono
parents:
diff changeset
264 void
kono
parents:
diff changeset
265 lra_delete_dead_insn (rtx_insn *insn)
kono
parents:
diff changeset
266 {
kono
parents:
diff changeset
267 rtx_insn *prev = prev_real_insn (insn);
kono
parents:
diff changeset
268 rtx prev_dest;
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 /* If the previous insn sets a register that dies in our insn,
kono
parents:
diff changeset
271 delete it too. */
kono
parents:
diff changeset
272 if (prev && GET_CODE (PATTERN (prev)) == SET
kono
parents:
diff changeset
273 && (prev_dest = SET_DEST (PATTERN (prev)), REG_P (prev_dest))
kono
parents:
diff changeset
274 && reg_mentioned_p (prev_dest, PATTERN (insn))
kono
parents:
diff changeset
275 && find_regno_note (insn, REG_DEAD, REGNO (prev_dest))
kono
parents:
diff changeset
276 && ! side_effects_p (SET_SRC (PATTERN (prev))))
kono
parents:
diff changeset
277 lra_delete_dead_insn (prev);
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 lra_set_insn_deleted (insn);
kono
parents:
diff changeset
280 }
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 /* Emit insn x = y + z. Return NULL if we failed to do it.
kono
parents:
diff changeset
283 Otherwise, return the insn. We don't use gen_add3_insn as it might
kono
parents:
diff changeset
284 clobber CC. */
kono
parents:
diff changeset
285 static rtx_insn *
kono
parents:
diff changeset
286 emit_add3_insn (rtx x, rtx y, rtx z)
kono
parents:
diff changeset
287 {
kono
parents:
diff changeset
288 rtx_insn *last;
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 last = get_last_insn ();
kono
parents:
diff changeset
291
kono
parents:
diff changeset
292 if (have_addptr3_insn (x, y, z))
kono
parents:
diff changeset
293 {
kono
parents:
diff changeset
294 rtx_insn *insn = gen_addptr3_insn (x, y, z);
kono
parents:
diff changeset
295
kono
parents:
diff changeset
296 /* If the target provides an "addptr" pattern it hopefully does
kono
parents:
diff changeset
297 for a reason. So falling back to the normal add would be
kono
parents:
diff changeset
298 a bug. */
kono
parents:
diff changeset
299 lra_assert (insn != NULL_RTX);
kono
parents:
diff changeset
300 emit_insn (insn);
kono
parents:
diff changeset
301 return insn;
kono
parents:
diff changeset
302 }
kono
parents:
diff changeset
303
kono
parents:
diff changeset
304 rtx_insn *insn = emit_insn (gen_rtx_SET (x, gen_rtx_PLUS (GET_MODE (y),
kono
parents:
diff changeset
305 y, z)));
kono
parents:
diff changeset
306 if (recog_memoized (insn) < 0)
kono
parents:
diff changeset
307 {
kono
parents:
diff changeset
308 delete_insns_since (last);
kono
parents:
diff changeset
309 insn = NULL;
kono
parents:
diff changeset
310 }
kono
parents:
diff changeset
311 return insn;
kono
parents:
diff changeset
312 }
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 /* Emit insn x = x + y. Return the insn. We use gen_add2_insn as the
kono
parents:
diff changeset
315 last resort. */
kono
parents:
diff changeset
316 static rtx_insn *
kono
parents:
diff changeset
317 emit_add2_insn (rtx x, rtx y)
kono
parents:
diff changeset
318 {
kono
parents:
diff changeset
319 rtx_insn *insn = emit_add3_insn (x, x, y);
kono
parents:
diff changeset
320 if (insn == NULL_RTX)
kono
parents:
diff changeset
321 {
kono
parents:
diff changeset
322 insn = gen_add2_insn (x, y);
kono
parents:
diff changeset
323 if (insn != NULL_RTX)
kono
parents:
diff changeset
324 emit_insn (insn);
kono
parents:
diff changeset
325 }
kono
parents:
diff changeset
326 return insn;
kono
parents:
diff changeset
327 }
kono
parents:
diff changeset
328
kono
parents:
diff changeset
329 /* Target checks operands through operand predicates to recognize an
kono
parents:
diff changeset
330 insn. We should have a special precaution to generate add insns
kono
parents:
diff changeset
331 which are frequent results of elimination.
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 Emit insns for x = y + z. X can be used to store intermediate
kono
parents:
diff changeset
334 values and should be not in Y and Z when we use X to store an
kono
parents:
diff changeset
335 intermediate value. Y + Z should form [base] [+ index[ * scale]] [
kono
parents:
diff changeset
336 + disp] where base and index are registers, disp and scale are
kono
parents:
diff changeset
337 constants. Y should contain base if it is present, Z should
kono
parents:
diff changeset
338 contain disp if any. index[*scale] can be part of Y or Z. */
kono
parents:
diff changeset
339 void
kono
parents:
diff changeset
340 lra_emit_add (rtx x, rtx y, rtx z)
kono
parents:
diff changeset
341 {
kono
parents:
diff changeset
342 int old;
kono
parents:
diff changeset
343 rtx_insn *last;
kono
parents:
diff changeset
344 rtx a1, a2, base, index, disp, scale, index_scale;
kono
parents:
diff changeset
345 bool ok_p;
kono
parents:
diff changeset
346
kono
parents:
diff changeset
347 rtx_insn *add3_insn = emit_add3_insn (x, y, z);
kono
parents:
diff changeset
348 old = max_reg_num ();
kono
parents:
diff changeset
349 if (add3_insn != NULL)
kono
parents:
diff changeset
350 ;
kono
parents:
diff changeset
351 else
kono
parents:
diff changeset
352 {
kono
parents:
diff changeset
353 disp = a2 = NULL_RTX;
kono
parents:
diff changeset
354 if (GET_CODE (y) == PLUS)
kono
parents:
diff changeset
355 {
kono
parents:
diff changeset
356 a1 = XEXP (y, 0);
kono
parents:
diff changeset
357 a2 = XEXP (y, 1);
kono
parents:
diff changeset
358 disp = z;
kono
parents:
diff changeset
359 }
kono
parents:
diff changeset
360 else
kono
parents:
diff changeset
361 {
kono
parents:
diff changeset
362 a1 = y;
kono
parents:
diff changeset
363 if (CONSTANT_P (z))
kono
parents:
diff changeset
364 disp = z;
kono
parents:
diff changeset
365 else
kono
parents:
diff changeset
366 a2 = z;
kono
parents:
diff changeset
367 }
kono
parents:
diff changeset
368 index_scale = scale = NULL_RTX;
kono
parents:
diff changeset
369 if (GET_CODE (a1) == MULT)
kono
parents:
diff changeset
370 {
kono
parents:
diff changeset
371 index_scale = a1;
kono
parents:
diff changeset
372 index = XEXP (a1, 0);
kono
parents:
diff changeset
373 scale = XEXP (a1, 1);
kono
parents:
diff changeset
374 base = a2;
kono
parents:
diff changeset
375 }
kono
parents:
diff changeset
376 else if (a2 != NULL_RTX && GET_CODE (a2) == MULT)
kono
parents:
diff changeset
377 {
kono
parents:
diff changeset
378 index_scale = a2;
kono
parents:
diff changeset
379 index = XEXP (a2, 0);
kono
parents:
diff changeset
380 scale = XEXP (a2, 1);
kono
parents:
diff changeset
381 base = a1;
kono
parents:
diff changeset
382 }
kono
parents:
diff changeset
383 else
kono
parents:
diff changeset
384 {
kono
parents:
diff changeset
385 base = a1;
kono
parents:
diff changeset
386 index = a2;
kono
parents:
diff changeset
387 }
kono
parents:
diff changeset
388 if ((base != NULL_RTX && ! (REG_P (base) || GET_CODE (base) == SUBREG))
kono
parents:
diff changeset
389 || (index != NULL_RTX
kono
parents:
diff changeset
390 && ! (REG_P (index) || GET_CODE (index) == SUBREG))
kono
parents:
diff changeset
391 || (disp != NULL_RTX && ! CONSTANT_P (disp))
kono
parents:
diff changeset
392 || (scale != NULL_RTX && ! CONSTANT_P (scale)))
kono
parents:
diff changeset
393 {
kono
parents:
diff changeset
394 /* Probably we have no 3 op add. Last chance is to use 2-op
kono
parents:
diff changeset
395 add insn. To succeed, don't move Z to X as an address
kono
parents:
diff changeset
396 segment always comes in Y. Otherwise, we might fail when
kono
parents:
diff changeset
397 adding the address segment to register. */
kono
parents:
diff changeset
398 lra_assert (x != y && x != z);
kono
parents:
diff changeset
399 emit_move_insn (x, y);
kono
parents:
diff changeset
400 rtx_insn *insn = emit_add2_insn (x, z);
kono
parents:
diff changeset
401 lra_assert (insn != NULL_RTX);
kono
parents:
diff changeset
402 }
kono
parents:
diff changeset
403 else
kono
parents:
diff changeset
404 {
kono
parents:
diff changeset
405 if (index_scale == NULL_RTX)
kono
parents:
diff changeset
406 index_scale = index;
kono
parents:
diff changeset
407 if (disp == NULL_RTX)
kono
parents:
diff changeset
408 {
kono
parents:
diff changeset
409 /* Generate x = index_scale; x = x + base. */
kono
parents:
diff changeset
410 lra_assert (index_scale != NULL_RTX && base != NULL_RTX);
kono
parents:
diff changeset
411 emit_move_insn (x, index_scale);
kono
parents:
diff changeset
412 rtx_insn *insn = emit_add2_insn (x, base);
kono
parents:
diff changeset
413 lra_assert (insn != NULL_RTX);
kono
parents:
diff changeset
414 }
kono
parents:
diff changeset
415 else if (scale == NULL_RTX)
kono
parents:
diff changeset
416 {
kono
parents:
diff changeset
417 /* Try x = base + disp. */
kono
parents:
diff changeset
418 lra_assert (base != NULL_RTX);
kono
parents:
diff changeset
419 last = get_last_insn ();
kono
parents:
diff changeset
420 rtx_insn *move_insn =
kono
parents:
diff changeset
421 emit_move_insn (x, gen_rtx_PLUS (GET_MODE (base), base, disp));
kono
parents:
diff changeset
422 if (recog_memoized (move_insn) < 0)
kono
parents:
diff changeset
423 {
kono
parents:
diff changeset
424 delete_insns_since (last);
kono
parents:
diff changeset
425 /* Generate x = disp; x = x + base. */
kono
parents:
diff changeset
426 emit_move_insn (x, disp);
kono
parents:
diff changeset
427 rtx_insn *add2_insn = emit_add2_insn (x, base);
kono
parents:
diff changeset
428 lra_assert (add2_insn != NULL_RTX);
kono
parents:
diff changeset
429 }
kono
parents:
diff changeset
430 /* Generate x = x + index. */
kono
parents:
diff changeset
431 if (index != NULL_RTX)
kono
parents:
diff changeset
432 {
kono
parents:
diff changeset
433 rtx_insn *insn = emit_add2_insn (x, index);
kono
parents:
diff changeset
434 lra_assert (insn != NULL_RTX);
kono
parents:
diff changeset
435 }
kono
parents:
diff changeset
436 }
kono
parents:
diff changeset
437 else
kono
parents:
diff changeset
438 {
kono
parents:
diff changeset
439 /* Try x = index_scale; x = x + disp; x = x + base. */
kono
parents:
diff changeset
440 last = get_last_insn ();
kono
parents:
diff changeset
441 rtx_insn *move_insn = emit_move_insn (x, index_scale);
kono
parents:
diff changeset
442 ok_p = false;
kono
parents:
diff changeset
443 if (recog_memoized (move_insn) >= 0)
kono
parents:
diff changeset
444 {
kono
parents:
diff changeset
445 rtx_insn *insn = emit_add2_insn (x, disp);
kono
parents:
diff changeset
446 if (insn != NULL_RTX)
kono
parents:
diff changeset
447 {
kono
parents:
diff changeset
448 if (base == NULL_RTX)
kono
parents:
diff changeset
449 ok_p = true;
kono
parents:
diff changeset
450 else
kono
parents:
diff changeset
451 {
kono
parents:
diff changeset
452 insn = emit_add2_insn (x, base);
kono
parents:
diff changeset
453 if (insn != NULL_RTX)
kono
parents:
diff changeset
454 ok_p = true;
kono
parents:
diff changeset
455 }
kono
parents:
diff changeset
456 }
kono
parents:
diff changeset
457 }
kono
parents:
diff changeset
458 if (! ok_p)
kono
parents:
diff changeset
459 {
kono
parents:
diff changeset
460 rtx_insn *insn;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 delete_insns_since (last);
kono
parents:
diff changeset
463 /* Generate x = disp; x = x + base; x = x + index_scale. */
kono
parents:
diff changeset
464 emit_move_insn (x, disp);
kono
parents:
diff changeset
465 if (base != NULL_RTX)
kono
parents:
diff changeset
466 {
kono
parents:
diff changeset
467 insn = emit_add2_insn (x, base);
kono
parents:
diff changeset
468 lra_assert (insn != NULL_RTX);
kono
parents:
diff changeset
469 }
kono
parents:
diff changeset
470 insn = emit_add2_insn (x, index_scale);
kono
parents:
diff changeset
471 lra_assert (insn != NULL_RTX);
kono
parents:
diff changeset
472 }
kono
parents:
diff changeset
473 }
kono
parents:
diff changeset
474 }
kono
parents:
diff changeset
475 }
kono
parents:
diff changeset
476 /* Functions emit_... can create pseudos -- so expand the pseudo
kono
parents:
diff changeset
477 data. */
kono
parents:
diff changeset
478 if (old != max_reg_num ())
kono
parents:
diff changeset
479 expand_reg_data (old);
kono
parents:
diff changeset
480 }
kono
parents:
diff changeset
481
kono
parents:
diff changeset
482 /* The number of emitted reload insns so far. */
kono
parents:
diff changeset
483 int lra_curr_reload_num;
kono
parents:
diff changeset
484
kono
parents:
diff changeset
485 /* Emit x := y, processing special case when y = u + v or y = u + v *
kono
parents:
diff changeset
486 scale + w through emit_add (Y can be an address which is base +
kono
parents:
diff changeset
487 index reg * scale + displacement in general case). X may be used
kono
parents:
diff changeset
488 as intermediate result therefore it should be not in Y. */
kono
parents:
diff changeset
489 void
kono
parents:
diff changeset
490 lra_emit_move (rtx x, rtx y)
kono
parents:
diff changeset
491 {
kono
parents:
diff changeset
492 int old;
kono
parents:
diff changeset
493
kono
parents:
diff changeset
494 if (GET_CODE (y) != PLUS)
kono
parents:
diff changeset
495 {
kono
parents:
diff changeset
496 if (rtx_equal_p (x, y))
kono
parents:
diff changeset
497 return;
kono
parents:
diff changeset
498 old = max_reg_num ();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
499 rtx_insn *insn = emit_move_insn (x, y);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
500 /* The move pattern may require scratch registers, so convert them
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
501 into real registers now. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
502 if (insn != NULL_RTX)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
503 remove_scratches_1 (insn);
111
kono
parents:
diff changeset
504 if (REG_P (x))
kono
parents:
diff changeset
505 lra_reg_info[ORIGINAL_REGNO (x)].last_reload = ++lra_curr_reload_num;
kono
parents:
diff changeset
506 /* Function emit_move can create pseudos -- so expand the pseudo
kono
parents:
diff changeset
507 data. */
kono
parents:
diff changeset
508 if (old != max_reg_num ())
kono
parents:
diff changeset
509 expand_reg_data (old);
kono
parents:
diff changeset
510 return;
kono
parents:
diff changeset
511 }
kono
parents:
diff changeset
512 lra_emit_add (x, XEXP (y, 0), XEXP (y, 1));
kono
parents:
diff changeset
513 }
kono
parents:
diff changeset
514
kono
parents:
diff changeset
515 /* Update insn operands which are duplication of operands whose
kono
parents:
diff changeset
516 numbers are in array of NOPS (with end marker -1). The insn is
kono
parents:
diff changeset
517 represented by its LRA internal representation ID. */
kono
parents:
diff changeset
518 void
kono
parents:
diff changeset
519 lra_update_dups (lra_insn_recog_data_t id, signed char *nops)
kono
parents:
diff changeset
520 {
kono
parents:
diff changeset
521 int i, j, nop;
kono
parents:
diff changeset
522 struct lra_static_insn_data *static_id = id->insn_static_data;
kono
parents:
diff changeset
523
kono
parents:
diff changeset
524 for (i = 0; i < static_id->n_dups; i++)
kono
parents:
diff changeset
525 for (j = 0; (nop = nops[j]) >= 0; j++)
kono
parents:
diff changeset
526 if (static_id->dup_num[i] == nop)
kono
parents:
diff changeset
527 *id->dup_loc[i] = *id->operand_loc[nop];
kono
parents:
diff changeset
528 }
kono
parents:
diff changeset
529
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531
kono
parents:
diff changeset
532 /* This page contains code dealing with info about registers in the
kono
parents:
diff changeset
533 insns. */
kono
parents:
diff changeset
534
kono
parents:
diff changeset
535 /* Pools for insn reg info. */
kono
parents:
diff changeset
536 object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
kono
parents:
diff changeset
537
kono
parents:
diff changeset
538 /* Create LRA insn related info about a reference to REGNO in INSN
kono
parents:
diff changeset
539 with TYPE (in/out/inout), biggest reference mode MODE, flag that it
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
540 is reference through subreg (SUBREG_P), and reference to the next
111
kono
parents:
diff changeset
541 insn reg info (NEXT). If REGNO can be early clobbered,
kono
parents:
diff changeset
542 alternatives in which it can be early clobbered are given by
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
543 EARLY_CLOBBER_ALTS. */
111
kono
parents:
diff changeset
544 static struct lra_insn_reg *
kono
parents:
diff changeset
545 new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
546 machine_mode mode, bool subreg_p,
111
kono
parents:
diff changeset
547 alternative_mask early_clobber_alts,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
548 struct lra_insn_reg *next)
111
kono
parents:
diff changeset
549 {
kono
parents:
diff changeset
550 lra_insn_reg *ir = lra_insn_reg_pool.allocate ();
kono
parents:
diff changeset
551 ir->type = type;
kono
parents:
diff changeset
552 ir->biggest_mode = mode;
kono
parents:
diff changeset
553 if (NONDEBUG_INSN_P (insn)
kono
parents:
diff changeset
554 && partial_subreg_p (lra_reg_info[regno].biggest_mode, mode))
kono
parents:
diff changeset
555 lra_reg_info[regno].biggest_mode = mode;
kono
parents:
diff changeset
556 ir->subreg_p = subreg_p;
kono
parents:
diff changeset
557 ir->early_clobber_alts = early_clobber_alts;
kono
parents:
diff changeset
558 ir->regno = regno;
kono
parents:
diff changeset
559 ir->next = next;
kono
parents:
diff changeset
560 return ir;
kono
parents:
diff changeset
561 }
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 /* Free insn reg info list IR. */
kono
parents:
diff changeset
564 static void
kono
parents:
diff changeset
565 free_insn_regs (struct lra_insn_reg *ir)
kono
parents:
diff changeset
566 {
kono
parents:
diff changeset
567 struct lra_insn_reg *next_ir;
kono
parents:
diff changeset
568
kono
parents:
diff changeset
569 for (; ir != NULL; ir = next_ir)
kono
parents:
diff changeset
570 {
kono
parents:
diff changeset
571 next_ir = ir->next;
kono
parents:
diff changeset
572 lra_insn_reg_pool.remove (ir);
kono
parents:
diff changeset
573 }
kono
parents:
diff changeset
574 }
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 /* Finish pool for insn reg info. */
kono
parents:
diff changeset
577 static void
kono
parents:
diff changeset
578 finish_insn_regs (void)
kono
parents:
diff changeset
579 {
kono
parents:
diff changeset
580 lra_insn_reg_pool.release ();
kono
parents:
diff changeset
581 }
kono
parents:
diff changeset
582
kono
parents:
diff changeset
583
kono
parents:
diff changeset
584
kono
parents:
diff changeset
585 /* This page contains code dealing LRA insn info (or in other words
kono
parents:
diff changeset
586 LRA internal insn representation). */
kono
parents:
diff changeset
587
kono
parents:
diff changeset
588 /* Map INSN_CODE -> the static insn data. This info is valid during
kono
parents:
diff changeset
589 all translation unit. */
kono
parents:
diff changeset
590 struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES];
kono
parents:
diff changeset
591
kono
parents:
diff changeset
592 /* Debug insns are represented as a special insn with one input
kono
parents:
diff changeset
593 operand which is RTL expression in var_location. */
kono
parents:
diff changeset
594
kono
parents:
diff changeset
595 /* The following data are used as static insn operand data for all
kono
parents:
diff changeset
596 debug insns. If structure lra_operand_data is changed, the
kono
parents:
diff changeset
597 initializer should be changed too. */
kono
parents:
diff changeset
598 static struct lra_operand_data debug_operand_data =
kono
parents:
diff changeset
599 {
kono
parents:
diff changeset
600 NULL, /* alternative */
kono
parents:
diff changeset
601 0, /* early_clobber_alts */
kono
parents:
diff changeset
602 E_VOIDmode, /* We are not interesting in the operand mode. */
kono
parents:
diff changeset
603 OP_IN,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
604 0, 0, 0
111
kono
parents:
diff changeset
605 };
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 /* The following data are used as static insn data for all debug
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
608 bind insns. If structure lra_static_insn_data is changed, the
111
kono
parents:
diff changeset
609 initializer should be changed too. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
610 static struct lra_static_insn_data debug_bind_static_data =
111
kono
parents:
diff changeset
611 {
kono
parents:
diff changeset
612 &debug_operand_data,
kono
parents:
diff changeset
613 0, /* Duplication operands #. */
kono
parents:
diff changeset
614 -1, /* Commutative operand #. */
kono
parents:
diff changeset
615 1, /* Operands #. There is only one operand which is debug RTL
kono
parents:
diff changeset
616 expression. */
kono
parents:
diff changeset
617 0, /* Duplications #. */
kono
parents:
diff changeset
618 0, /* Alternatives #. We are not interesting in alternatives
kono
parents:
diff changeset
619 because we does not proceed debug_insns for reloads. */
kono
parents:
diff changeset
620 NULL, /* Hard registers referenced in machine description. */
kono
parents:
diff changeset
621 NULL /* Descriptions of operands in alternatives. */
kono
parents:
diff changeset
622 };
kono
parents:
diff changeset
623
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
624 /* The following data are used as static insn data for all debug
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
625 marker insns. If structure lra_static_insn_data is changed, the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
626 initializer should be changed too. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
627 static struct lra_static_insn_data debug_marker_static_data =
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
628 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
629 &debug_operand_data,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
630 0, /* Duplication operands #. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
631 -1, /* Commutative operand #. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
632 0, /* Operands #. There isn't any operand. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
633 0, /* Duplications #. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
634 0, /* Alternatives #. We are not interesting in alternatives
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
635 because we does not proceed debug_insns for reloads. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
636 NULL, /* Hard registers referenced in machine description. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
637 NULL /* Descriptions of operands in alternatives. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
638 };
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
639
111
kono
parents:
diff changeset
640 /* Called once per compiler work to initialize some LRA data related
kono
parents:
diff changeset
641 to insns. */
kono
parents:
diff changeset
642 static void
kono
parents:
diff changeset
643 init_insn_code_data_once (void)
kono
parents:
diff changeset
644 {
kono
parents:
diff changeset
645 memset (insn_code_data, 0, sizeof (insn_code_data));
kono
parents:
diff changeset
646 }
kono
parents:
diff changeset
647
kono
parents:
diff changeset
648 /* Called once per compiler work to finalize some LRA data related to
kono
parents:
diff changeset
649 insns. */
kono
parents:
diff changeset
650 static void
kono
parents:
diff changeset
651 finish_insn_code_data_once (void)
kono
parents:
diff changeset
652 {
kono
parents:
diff changeset
653 for (unsigned int i = 0; i < NUM_INSN_CODES; i++)
kono
parents:
diff changeset
654 {
kono
parents:
diff changeset
655 if (insn_code_data[i] != NULL)
kono
parents:
diff changeset
656 free (insn_code_data[i]);
kono
parents:
diff changeset
657 }
kono
parents:
diff changeset
658 }
kono
parents:
diff changeset
659
kono
parents:
diff changeset
660 /* Return static insn data, allocate and setup if necessary. Although
kono
parents:
diff changeset
661 dup_num is static data (it depends only on icode), to set it up we
kono
parents:
diff changeset
662 need to extract insn first. So recog_data should be valid for
kono
parents:
diff changeset
663 normal insn (ICODE >= 0) before the call. */
kono
parents:
diff changeset
664 static struct lra_static_insn_data *
kono
parents:
diff changeset
665 get_static_insn_data (int icode, int nop, int ndup, int nalt)
kono
parents:
diff changeset
666 {
kono
parents:
diff changeset
667 struct lra_static_insn_data *data;
kono
parents:
diff changeset
668 size_t n_bytes;
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 lra_assert (icode < (int) NUM_INSN_CODES);
kono
parents:
diff changeset
671 if (icode >= 0 && (data = insn_code_data[icode]) != NULL)
kono
parents:
diff changeset
672 return data;
kono
parents:
diff changeset
673 lra_assert (nop >= 0 && ndup >= 0 && nalt >= 0);
kono
parents:
diff changeset
674 n_bytes = sizeof (struct lra_static_insn_data)
kono
parents:
diff changeset
675 + sizeof (struct lra_operand_data) * nop
kono
parents:
diff changeset
676 + sizeof (int) * ndup;
kono
parents:
diff changeset
677 data = XNEWVAR (struct lra_static_insn_data, n_bytes);
kono
parents:
diff changeset
678 data->operand_alternative = NULL;
kono
parents:
diff changeset
679 data->n_operands = nop;
kono
parents:
diff changeset
680 data->n_dups = ndup;
kono
parents:
diff changeset
681 data->n_alternatives = nalt;
kono
parents:
diff changeset
682 data->operand = ((struct lra_operand_data *)
kono
parents:
diff changeset
683 ((char *) data + sizeof (struct lra_static_insn_data)));
kono
parents:
diff changeset
684 data->dup_num = ((int *) ((char *) data->operand
kono
parents:
diff changeset
685 + sizeof (struct lra_operand_data) * nop));
kono
parents:
diff changeset
686 if (icode >= 0)
kono
parents:
diff changeset
687 {
kono
parents:
diff changeset
688 int i;
kono
parents:
diff changeset
689
kono
parents:
diff changeset
690 insn_code_data[icode] = data;
kono
parents:
diff changeset
691 for (i = 0; i < nop; i++)
kono
parents:
diff changeset
692 {
kono
parents:
diff changeset
693 data->operand[i].constraint
kono
parents:
diff changeset
694 = insn_data[icode].operand[i].constraint;
kono
parents:
diff changeset
695 data->operand[i].mode = insn_data[icode].operand[i].mode;
kono
parents:
diff changeset
696 data->operand[i].strict_low = insn_data[icode].operand[i].strict_low;
kono
parents:
diff changeset
697 data->operand[i].is_operator
kono
parents:
diff changeset
698 = insn_data[icode].operand[i].is_operator;
kono
parents:
diff changeset
699 data->operand[i].type
kono
parents:
diff changeset
700 = (data->operand[i].constraint[0] == '=' ? OP_OUT
kono
parents:
diff changeset
701 : data->operand[i].constraint[0] == '+' ? OP_INOUT
kono
parents:
diff changeset
702 : OP_IN);
kono
parents:
diff changeset
703 data->operand[i].is_address = false;
kono
parents:
diff changeset
704 }
kono
parents:
diff changeset
705 for (i = 0; i < ndup; i++)
kono
parents:
diff changeset
706 data->dup_num[i] = recog_data.dup_num[i];
kono
parents:
diff changeset
707 }
kono
parents:
diff changeset
708 return data;
kono
parents:
diff changeset
709 }
kono
parents:
diff changeset
710
kono
parents:
diff changeset
711 /* The current length of the following array. */
kono
parents:
diff changeset
712 int lra_insn_recog_data_len;
kono
parents:
diff changeset
713
kono
parents:
diff changeset
714 /* Map INSN_UID -> the insn recog data (NULL if unknown). */
kono
parents:
diff changeset
715 lra_insn_recog_data_t *lra_insn_recog_data;
kono
parents:
diff changeset
716
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
717 /* Alloc pool we allocate entries for lra_insn_recog_data from. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
718 static object_allocator<class lra_insn_recog_data>
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
719 lra_insn_recog_data_pool ("insn recog data pool");
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
720
111
kono
parents:
diff changeset
721 /* Initialize LRA data about insns. */
kono
parents:
diff changeset
722 static void
kono
parents:
diff changeset
723 init_insn_recog_data (void)
kono
parents:
diff changeset
724 {
kono
parents:
diff changeset
725 lra_insn_recog_data_len = 0;
kono
parents:
diff changeset
726 lra_insn_recog_data = NULL;
kono
parents:
diff changeset
727 }
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 /* Expand, if necessary, LRA data about insns. */
kono
parents:
diff changeset
730 static void
kono
parents:
diff changeset
731 check_and_expand_insn_recog_data (int index)
kono
parents:
diff changeset
732 {
kono
parents:
diff changeset
733 int i, old;
kono
parents:
diff changeset
734
kono
parents:
diff changeset
735 if (lra_insn_recog_data_len > index)
kono
parents:
diff changeset
736 return;
kono
parents:
diff changeset
737 old = lra_insn_recog_data_len;
kono
parents:
diff changeset
738 lra_insn_recog_data_len = index * 3 / 2 + 1;
kono
parents:
diff changeset
739 lra_insn_recog_data = XRESIZEVEC (lra_insn_recog_data_t,
kono
parents:
diff changeset
740 lra_insn_recog_data,
kono
parents:
diff changeset
741 lra_insn_recog_data_len);
kono
parents:
diff changeset
742 for (i = old; i < lra_insn_recog_data_len; i++)
kono
parents:
diff changeset
743 lra_insn_recog_data[i] = NULL;
kono
parents:
diff changeset
744 }
kono
parents:
diff changeset
745
kono
parents:
diff changeset
746 /* Finish LRA DATA about insn. */
kono
parents:
diff changeset
747 static void
kono
parents:
diff changeset
748 free_insn_recog_data (lra_insn_recog_data_t data)
kono
parents:
diff changeset
749 {
kono
parents:
diff changeset
750 if (data->operand_loc != NULL)
kono
parents:
diff changeset
751 free (data->operand_loc);
kono
parents:
diff changeset
752 if (data->dup_loc != NULL)
kono
parents:
diff changeset
753 free (data->dup_loc);
kono
parents:
diff changeset
754 if (data->arg_hard_regs != NULL)
kono
parents:
diff changeset
755 free (data->arg_hard_regs);
kono
parents:
diff changeset
756 if (data->icode < 0 && NONDEBUG_INSN_P (data->insn))
kono
parents:
diff changeset
757 {
kono
parents:
diff changeset
758 if (data->insn_static_data->operand_alternative != NULL)
kono
parents:
diff changeset
759 free (const_cast <operand_alternative *>
kono
parents:
diff changeset
760 (data->insn_static_data->operand_alternative));
kono
parents:
diff changeset
761 free_insn_regs (data->insn_static_data->hard_regs);
kono
parents:
diff changeset
762 free (data->insn_static_data);
kono
parents:
diff changeset
763 }
kono
parents:
diff changeset
764 free_insn_regs (data->regs);
kono
parents:
diff changeset
765 data->regs = NULL;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
766 lra_insn_recog_data_pool.remove (data);
111
kono
parents:
diff changeset
767 }
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 /* Pools for copies. */
kono
parents:
diff changeset
770 static object_allocator<lra_copy> lra_copy_pool ("lra copies");
kono
parents:
diff changeset
771
kono
parents:
diff changeset
772 /* Finish LRA data about all insns. */
kono
parents:
diff changeset
773 static void
kono
parents:
diff changeset
774 finish_insn_recog_data (void)
kono
parents:
diff changeset
775 {
kono
parents:
diff changeset
776 int i;
kono
parents:
diff changeset
777 lra_insn_recog_data_t data;
kono
parents:
diff changeset
778
kono
parents:
diff changeset
779 for (i = 0; i < lra_insn_recog_data_len; i++)
kono
parents:
diff changeset
780 if ((data = lra_insn_recog_data[i]) != NULL)
kono
parents:
diff changeset
781 free_insn_recog_data (data);
kono
parents:
diff changeset
782 finish_insn_regs ();
kono
parents:
diff changeset
783 lra_copy_pool.release ();
kono
parents:
diff changeset
784 lra_insn_reg_pool.release ();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
785 lra_insn_recog_data_pool.release ();
111
kono
parents:
diff changeset
786 free (lra_insn_recog_data);
kono
parents:
diff changeset
787 }
kono
parents:
diff changeset
788
kono
parents:
diff changeset
789 /* Setup info about operands in alternatives of LRA DATA of insn. */
kono
parents:
diff changeset
790 static void
kono
parents:
diff changeset
791 setup_operand_alternative (lra_insn_recog_data_t data,
kono
parents:
diff changeset
792 const operand_alternative *op_alt)
kono
parents:
diff changeset
793 {
kono
parents:
diff changeset
794 int i, j, nop, nalt;
kono
parents:
diff changeset
795 int icode = data->icode;
kono
parents:
diff changeset
796 struct lra_static_insn_data *static_data = data->insn_static_data;
kono
parents:
diff changeset
797
kono
parents:
diff changeset
798 static_data->commutative = -1;
kono
parents:
diff changeset
799 nop = static_data->n_operands;
kono
parents:
diff changeset
800 nalt = static_data->n_alternatives;
kono
parents:
diff changeset
801 static_data->operand_alternative = op_alt;
kono
parents:
diff changeset
802 for (i = 0; i < nop; i++)
kono
parents:
diff changeset
803 {
kono
parents:
diff changeset
804 static_data->operand[i].early_clobber_alts = 0;
kono
parents:
diff changeset
805 static_data->operand[i].is_address = false;
kono
parents:
diff changeset
806 if (static_data->operand[i].constraint[0] == '%')
kono
parents:
diff changeset
807 {
kono
parents:
diff changeset
808 /* We currently only support one commutative pair of operands. */
kono
parents:
diff changeset
809 if (static_data->commutative < 0)
kono
parents:
diff changeset
810 static_data->commutative = i;
kono
parents:
diff changeset
811 else
kono
parents:
diff changeset
812 lra_assert (icode < 0); /* Asm */
kono
parents:
diff changeset
813 /* The last operand should not be marked commutative. */
kono
parents:
diff changeset
814 lra_assert (i != nop - 1);
kono
parents:
diff changeset
815 }
kono
parents:
diff changeset
816 }
kono
parents:
diff changeset
817 for (j = 0; j < nalt; j++)
kono
parents:
diff changeset
818 for (i = 0; i < nop; i++, op_alt++)
kono
parents:
diff changeset
819 {
kono
parents:
diff changeset
820 if (op_alt->earlyclobber)
kono
parents:
diff changeset
821 static_data->operand[i].early_clobber_alts |= (alternative_mask) 1 << j;
kono
parents:
diff changeset
822 static_data->operand[i].is_address |= op_alt->is_address;
kono
parents:
diff changeset
823 }
kono
parents:
diff changeset
824 }
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 /* Recursively process X and collect info about registers, which are
kono
parents:
diff changeset
827 not the insn operands, in X with TYPE (in/out/inout) and flag that
kono
parents:
diff changeset
828 it is early clobbered in the insn (EARLY_CLOBBER) and add the info
kono
parents:
diff changeset
829 to LIST. X is a part of insn given by DATA. Return the result
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
830 list. */
111
kono
parents:
diff changeset
831 static struct lra_insn_reg *
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
832 collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
833 lra_insn_recog_data_t data,
111
kono
parents:
diff changeset
834 struct lra_insn_reg *list,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
835 enum op_type type, bool early_clobber)
111
kono
parents:
diff changeset
836 {
kono
parents:
diff changeset
837 int i, j, regno, last;
kono
parents:
diff changeset
838 bool subreg_p;
kono
parents:
diff changeset
839 machine_mode mode;
kono
parents:
diff changeset
840 struct lra_insn_reg *curr;
kono
parents:
diff changeset
841 rtx op = *x;
kono
parents:
diff changeset
842 enum rtx_code code = GET_CODE (op);
kono
parents:
diff changeset
843 const char *fmt = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
844
kono
parents:
diff changeset
845 for (i = 0; i < data->insn_static_data->n_operands; i++)
kono
parents:
diff changeset
846 if (! data->insn_static_data->operand[i].is_operator
kono
parents:
diff changeset
847 && x == data->operand_loc[i])
kono
parents:
diff changeset
848 /* It is an operand loc. Stop here. */
kono
parents:
diff changeset
849 return list;
kono
parents:
diff changeset
850 for (i = 0; i < data->insn_static_data->n_dups; i++)
kono
parents:
diff changeset
851 if (x == data->dup_loc[i])
kono
parents:
diff changeset
852 /* It is a dup loc. Stop here. */
kono
parents:
diff changeset
853 return list;
kono
parents:
diff changeset
854 mode = GET_MODE (op);
kono
parents:
diff changeset
855 subreg_p = false;
kono
parents:
diff changeset
856 if (code == SUBREG)
kono
parents:
diff changeset
857 {
kono
parents:
diff changeset
858 mode = wider_subreg_mode (op);
kono
parents:
diff changeset
859 if (read_modify_subreg_p (op))
kono
parents:
diff changeset
860 subreg_p = true;
kono
parents:
diff changeset
861 op = SUBREG_REG (op);
kono
parents:
diff changeset
862 code = GET_CODE (op);
kono
parents:
diff changeset
863 }
kono
parents:
diff changeset
864 if (REG_P (op))
kono
parents:
diff changeset
865 {
kono
parents:
diff changeset
866 if ((regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
867 return list;
kono
parents:
diff changeset
868 /* Process all regs even unallocatable ones as we need info
kono
parents:
diff changeset
869 about all regs for rematerialization pass. */
kono
parents:
diff changeset
870 for (last = end_hard_regno (mode, regno); regno < last; regno++)
kono
parents:
diff changeset
871 {
kono
parents:
diff changeset
872 for (curr = list; curr != NULL; curr = curr->next)
kono
parents:
diff changeset
873 if (curr->regno == regno && curr->subreg_p == subreg_p
kono
parents:
diff changeset
874 && curr->biggest_mode == mode)
kono
parents:
diff changeset
875 {
kono
parents:
diff changeset
876 if (curr->type != type)
kono
parents:
diff changeset
877 curr->type = OP_INOUT;
kono
parents:
diff changeset
878 if (early_clobber)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
879 curr->early_clobber_alts = ALL_ALTERNATIVES;
111
kono
parents:
diff changeset
880 break;
kono
parents:
diff changeset
881 }
kono
parents:
diff changeset
882 if (curr == NULL)
kono
parents:
diff changeset
883 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
884 /* This is a new hard regno or the info cannot be
111
kono
parents:
diff changeset
885 integrated into the found structure. */
kono
parents:
diff changeset
886 #ifdef STACK_REGS
kono
parents:
diff changeset
887 early_clobber
kono
parents:
diff changeset
888 = (early_clobber
kono
parents:
diff changeset
889 /* This clobber is to inform popping floating
kono
parents:
diff changeset
890 point stack only. */
kono
parents:
diff changeset
891 && ! (FIRST_STACK_REG <= regno
kono
parents:
diff changeset
892 && regno <= LAST_STACK_REG));
kono
parents:
diff changeset
893 #endif
kono
parents:
diff changeset
894 list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
895 early_clobber ? ALL_ALTERNATIVES : 0, list);
111
kono
parents:
diff changeset
896 }
kono
parents:
diff changeset
897 }
kono
parents:
diff changeset
898 return list;
kono
parents:
diff changeset
899 }
kono
parents:
diff changeset
900 switch (code)
kono
parents:
diff changeset
901 {
kono
parents:
diff changeset
902 case SET:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
903 list = collect_non_operand_hard_regs (insn, &SET_DEST (op), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
904 list, OP_OUT, false);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
905 list = collect_non_operand_hard_regs (insn, &SET_SRC (op), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
906 list, OP_IN, false);
111
kono
parents:
diff changeset
907 break;
kono
parents:
diff changeset
908 case CLOBBER:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
909 /* We treat clobber of non-operand hard registers as early clobber. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
910 list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
911 list, OP_OUT, true);
111
kono
parents:
diff changeset
912 break;
kono
parents:
diff changeset
913 case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
914 list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
915 list, OP_INOUT, false);
111
kono
parents:
diff changeset
916 break;
kono
parents:
diff changeset
917 case PRE_MODIFY: case POST_MODIFY:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
918 list = collect_non_operand_hard_regs (insn, &XEXP (op, 0), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
919 list, OP_INOUT, false);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
920 list = collect_non_operand_hard_regs (insn, &XEXP (op, 1), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
921 list, OP_IN, false);
111
kono
parents:
diff changeset
922 break;
kono
parents:
diff changeset
923 default:
kono
parents:
diff changeset
924 fmt = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
925 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
kono
parents:
diff changeset
926 {
kono
parents:
diff changeset
927 if (fmt[i] == 'e')
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
928 list = collect_non_operand_hard_regs (insn, &XEXP (op, i), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
929 list, OP_IN, false);
111
kono
parents:
diff changeset
930 else if (fmt[i] == 'E')
kono
parents:
diff changeset
931 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
932 list = collect_non_operand_hard_regs (insn, &XVECEXP (op, i, j),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
933 data, list, OP_IN, false);
111
kono
parents:
diff changeset
934 }
kono
parents:
diff changeset
935 }
kono
parents:
diff changeset
936 return list;
kono
parents:
diff changeset
937 }
kono
parents:
diff changeset
938
kono
parents:
diff changeset
939 /* Set up and return info about INSN. Set up the info if it is not set up
kono
parents:
diff changeset
940 yet. */
kono
parents:
diff changeset
941 lra_insn_recog_data_t
kono
parents:
diff changeset
942 lra_set_insn_recog_data (rtx_insn *insn)
kono
parents:
diff changeset
943 {
kono
parents:
diff changeset
944 lra_insn_recog_data_t data;
kono
parents:
diff changeset
945 int i, n, icode;
kono
parents:
diff changeset
946 rtx **locs;
kono
parents:
diff changeset
947 unsigned int uid = INSN_UID (insn);
kono
parents:
diff changeset
948 struct lra_static_insn_data *insn_static_data;
kono
parents:
diff changeset
949
kono
parents:
diff changeset
950 check_and_expand_insn_recog_data (uid);
kono
parents:
diff changeset
951 if (DEBUG_INSN_P (insn))
kono
parents:
diff changeset
952 icode = -1;
kono
parents:
diff changeset
953 else
kono
parents:
diff changeset
954 {
kono
parents:
diff changeset
955 icode = INSN_CODE (insn);
kono
parents:
diff changeset
956 if (icode < 0)
kono
parents:
diff changeset
957 /* It might be a new simple insn which is not recognized yet. */
kono
parents:
diff changeset
958 INSN_CODE (insn) = icode = recog_memoized (insn);
kono
parents:
diff changeset
959 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
960 data = lra_insn_recog_data_pool.allocate ();
111
kono
parents:
diff changeset
961 lra_insn_recog_data[uid] = data;
kono
parents:
diff changeset
962 data->insn = insn;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
963 data->used_insn_alternative = LRA_UNKNOWN_ALT;
111
kono
parents:
diff changeset
964 data->icode = icode;
kono
parents:
diff changeset
965 data->regs = NULL;
kono
parents:
diff changeset
966 if (DEBUG_INSN_P (insn))
kono
parents:
diff changeset
967 {
kono
parents:
diff changeset
968 data->dup_loc = NULL;
kono
parents:
diff changeset
969 data->arg_hard_regs = NULL;
kono
parents:
diff changeset
970 data->preferred_alternatives = ALL_ALTERNATIVES;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
971 if (DEBUG_BIND_INSN_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
972 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
973 data->insn_static_data = &debug_bind_static_data;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
974 data->operand_loc = XNEWVEC (rtx *, 1);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
975 data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
976 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
977 else if (DEBUG_MARKER_INSN_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
978 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
979 data->insn_static_data = &debug_marker_static_data;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
980 data->operand_loc = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
981 }
111
kono
parents:
diff changeset
982 return data;
kono
parents:
diff changeset
983 }
kono
parents:
diff changeset
984 if (icode < 0)
kono
parents:
diff changeset
985 {
kono
parents:
diff changeset
986 int nop, nalt;
kono
parents:
diff changeset
987 machine_mode operand_mode[MAX_RECOG_OPERANDS];
kono
parents:
diff changeset
988 const char *constraints[MAX_RECOG_OPERANDS];
kono
parents:
diff changeset
989
kono
parents:
diff changeset
990 nop = asm_noperands (PATTERN (insn));
kono
parents:
diff changeset
991 data->operand_loc = data->dup_loc = NULL;
kono
parents:
diff changeset
992 nalt = 1;
kono
parents:
diff changeset
993 if (nop < 0)
kono
parents:
diff changeset
994 {
kono
parents:
diff changeset
995 /* It is a special insn like USE or CLOBBER. We should
kono
parents:
diff changeset
996 recognize any regular insn otherwise LRA can do nothing
kono
parents:
diff changeset
997 with this insn. */
kono
parents:
diff changeset
998 gcc_assert (GET_CODE (PATTERN (insn)) == USE
kono
parents:
diff changeset
999 || GET_CODE (PATTERN (insn)) == CLOBBER
kono
parents:
diff changeset
1000 || GET_CODE (PATTERN (insn)) == ASM_INPUT);
kono
parents:
diff changeset
1001 data->insn_static_data = insn_static_data
kono
parents:
diff changeset
1002 = get_static_insn_data (-1, 0, 0, nalt);
kono
parents:
diff changeset
1003 }
kono
parents:
diff changeset
1004 else
kono
parents:
diff changeset
1005 {
kono
parents:
diff changeset
1006 /* expand_asm_operands makes sure there aren't too many
kono
parents:
diff changeset
1007 operands. */
kono
parents:
diff changeset
1008 lra_assert (nop <= MAX_RECOG_OPERANDS);
kono
parents:
diff changeset
1009 if (nop != 0)
kono
parents:
diff changeset
1010 data->operand_loc = XNEWVEC (rtx *, nop);
kono
parents:
diff changeset
1011 /* Now get the operand values and constraints out of the
kono
parents:
diff changeset
1012 insn. */
kono
parents:
diff changeset
1013 decode_asm_operands (PATTERN (insn), NULL,
kono
parents:
diff changeset
1014 data->operand_loc,
kono
parents:
diff changeset
1015 constraints, operand_mode, NULL);
kono
parents:
diff changeset
1016 if (nop > 0)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1017 for (const char *p =constraints[0]; *p; p++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1018 nalt += *p == ',';
111
kono
parents:
diff changeset
1019 data->insn_static_data = insn_static_data
kono
parents:
diff changeset
1020 = get_static_insn_data (-1, nop, 0, nalt);
kono
parents:
diff changeset
1021 for (i = 0; i < nop; i++)
kono
parents:
diff changeset
1022 {
kono
parents:
diff changeset
1023 insn_static_data->operand[i].mode = operand_mode[i];
kono
parents:
diff changeset
1024 insn_static_data->operand[i].constraint = constraints[i];
kono
parents:
diff changeset
1025 insn_static_data->operand[i].strict_low = false;
kono
parents:
diff changeset
1026 insn_static_data->operand[i].is_operator = false;
kono
parents:
diff changeset
1027 insn_static_data->operand[i].is_address = false;
kono
parents:
diff changeset
1028 }
kono
parents:
diff changeset
1029 }
kono
parents:
diff changeset
1030 for (i = 0; i < insn_static_data->n_operands; i++)
kono
parents:
diff changeset
1031 insn_static_data->operand[i].type
kono
parents:
diff changeset
1032 = (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
kono
parents:
diff changeset
1033 : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
kono
parents:
diff changeset
1034 : OP_IN);
kono
parents:
diff changeset
1035 data->preferred_alternatives = ALL_ALTERNATIVES;
kono
parents:
diff changeset
1036 if (nop > 0)
kono
parents:
diff changeset
1037 {
kono
parents:
diff changeset
1038 operand_alternative *op_alt = XCNEWVEC (operand_alternative,
kono
parents:
diff changeset
1039 nalt * nop);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1040 preprocess_constraints (nop, nalt, constraints, op_alt,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1041 data->operand_loc);
111
kono
parents:
diff changeset
1042 setup_operand_alternative (data, op_alt);
kono
parents:
diff changeset
1043 }
kono
parents:
diff changeset
1044 }
kono
parents:
diff changeset
1045 else
kono
parents:
diff changeset
1046 {
kono
parents:
diff changeset
1047 insn_extract (insn);
kono
parents:
diff changeset
1048 data->insn_static_data = insn_static_data
kono
parents:
diff changeset
1049 = get_static_insn_data (icode, insn_data[icode].n_operands,
kono
parents:
diff changeset
1050 insn_data[icode].n_dups,
kono
parents:
diff changeset
1051 insn_data[icode].n_alternatives);
kono
parents:
diff changeset
1052 n = insn_static_data->n_operands;
kono
parents:
diff changeset
1053 if (n == 0)
kono
parents:
diff changeset
1054 locs = NULL;
kono
parents:
diff changeset
1055 else
kono
parents:
diff changeset
1056 {
kono
parents:
diff changeset
1057 locs = XNEWVEC (rtx *, n);
kono
parents:
diff changeset
1058 memcpy (locs, recog_data.operand_loc, n * sizeof (rtx *));
kono
parents:
diff changeset
1059 }
kono
parents:
diff changeset
1060 data->operand_loc = locs;
kono
parents:
diff changeset
1061 n = insn_static_data->n_dups;
kono
parents:
diff changeset
1062 if (n == 0)
kono
parents:
diff changeset
1063 locs = NULL;
kono
parents:
diff changeset
1064 else
kono
parents:
diff changeset
1065 {
kono
parents:
diff changeset
1066 locs = XNEWVEC (rtx *, n);
kono
parents:
diff changeset
1067 memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *));
kono
parents:
diff changeset
1068 }
kono
parents:
diff changeset
1069 data->dup_loc = locs;
kono
parents:
diff changeset
1070 data->preferred_alternatives = get_preferred_alternatives (insn);
kono
parents:
diff changeset
1071 const operand_alternative *op_alt = preprocess_insn_constraints (icode);
kono
parents:
diff changeset
1072 if (!insn_static_data->operand_alternative)
kono
parents:
diff changeset
1073 setup_operand_alternative (data, op_alt);
kono
parents:
diff changeset
1074 else if (op_alt != insn_static_data->operand_alternative)
kono
parents:
diff changeset
1075 insn_static_data->operand_alternative = op_alt;
kono
parents:
diff changeset
1076 }
kono
parents:
diff changeset
1077 if (GET_CODE (PATTERN (insn)) == CLOBBER || GET_CODE (PATTERN (insn)) == USE)
kono
parents:
diff changeset
1078 insn_static_data->hard_regs = NULL;
kono
parents:
diff changeset
1079 else
kono
parents:
diff changeset
1080 insn_static_data->hard_regs
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1081 = collect_non_operand_hard_regs (insn, &PATTERN (insn), data,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1082 NULL, OP_IN, false);
111
kono
parents:
diff changeset
1083 data->arg_hard_regs = NULL;
kono
parents:
diff changeset
1084 if (CALL_P (insn))
kono
parents:
diff changeset
1085 {
kono
parents:
diff changeset
1086 bool use_p;
kono
parents:
diff changeset
1087 rtx link;
kono
parents:
diff changeset
1088 int n_hard_regs, regno, arg_hard_regs[FIRST_PSEUDO_REGISTER];
kono
parents:
diff changeset
1089
kono
parents:
diff changeset
1090 n_hard_regs = 0;
kono
parents:
diff changeset
1091 /* Finding implicit hard register usage. We believe it will be
kono
parents:
diff changeset
1092 not changed whatever transformations are used. Call insns
kono
parents:
diff changeset
1093 are such example. */
kono
parents:
diff changeset
1094 for (link = CALL_INSN_FUNCTION_USAGE (insn);
kono
parents:
diff changeset
1095 link != NULL_RTX;
kono
parents:
diff changeset
1096 link = XEXP (link, 1))
kono
parents:
diff changeset
1097 if (((use_p = GET_CODE (XEXP (link, 0)) == USE)
kono
parents:
diff changeset
1098 || GET_CODE (XEXP (link, 0)) == CLOBBER)
kono
parents:
diff changeset
1099 && REG_P (XEXP (XEXP (link, 0), 0)))
kono
parents:
diff changeset
1100 {
kono
parents:
diff changeset
1101 regno = REGNO (XEXP (XEXP (link, 0), 0));
kono
parents:
diff changeset
1102 lra_assert (regno < FIRST_PSEUDO_REGISTER);
kono
parents:
diff changeset
1103 /* It is an argument register. */
kono
parents:
diff changeset
1104 for (i = REG_NREGS (XEXP (XEXP (link, 0), 0)) - 1; i >= 0; i--)
kono
parents:
diff changeset
1105 arg_hard_regs[n_hard_regs++]
kono
parents:
diff changeset
1106 = regno + i + (use_p ? 0 : FIRST_PSEUDO_REGISTER);
kono
parents:
diff changeset
1107 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1108
111
kono
parents:
diff changeset
1109 if (n_hard_regs != 0)
kono
parents:
diff changeset
1110 {
kono
parents:
diff changeset
1111 arg_hard_regs[n_hard_regs++] = -1;
kono
parents:
diff changeset
1112 data->arg_hard_regs = XNEWVEC (int, n_hard_regs);
kono
parents:
diff changeset
1113 memcpy (data->arg_hard_regs, arg_hard_regs,
kono
parents:
diff changeset
1114 sizeof (int) * n_hard_regs);
kono
parents:
diff changeset
1115 }
kono
parents:
diff changeset
1116 }
kono
parents:
diff changeset
1117 /* Some output operand can be recognized only from the context not
kono
parents:
diff changeset
1118 from the constraints which are empty in this case. Call insn may
kono
parents:
diff changeset
1119 contain a hard register in set destination with empty constraint
kono
parents:
diff changeset
1120 and extract_insn treats them as an input. */
kono
parents:
diff changeset
1121 for (i = 0; i < insn_static_data->n_operands; i++)
kono
parents:
diff changeset
1122 {
kono
parents:
diff changeset
1123 int j;
kono
parents:
diff changeset
1124 rtx pat, set;
kono
parents:
diff changeset
1125 struct lra_operand_data *operand = &insn_static_data->operand[i];
kono
parents:
diff changeset
1126
kono
parents:
diff changeset
1127 /* ??? Should we treat 'X' the same way. It looks to me that
kono
parents:
diff changeset
1128 'X' means anything and empty constraint means we do not
kono
parents:
diff changeset
1129 care. */
kono
parents:
diff changeset
1130 if (operand->type != OP_IN || *operand->constraint != '\0'
kono
parents:
diff changeset
1131 || operand->is_operator)
kono
parents:
diff changeset
1132 continue;
kono
parents:
diff changeset
1133 pat = PATTERN (insn);
kono
parents:
diff changeset
1134 if (GET_CODE (pat) == SET)
kono
parents:
diff changeset
1135 {
kono
parents:
diff changeset
1136 if (data->operand_loc[i] != &SET_DEST (pat))
kono
parents:
diff changeset
1137 continue;
kono
parents:
diff changeset
1138 }
kono
parents:
diff changeset
1139 else if (GET_CODE (pat) == PARALLEL)
kono
parents:
diff changeset
1140 {
kono
parents:
diff changeset
1141 for (j = XVECLEN (pat, 0) - 1; j >= 0; j--)
kono
parents:
diff changeset
1142 {
kono
parents:
diff changeset
1143 set = XVECEXP (PATTERN (insn), 0, j);
kono
parents:
diff changeset
1144 if (GET_CODE (set) == SET
kono
parents:
diff changeset
1145 && &SET_DEST (set) == data->operand_loc[i])
kono
parents:
diff changeset
1146 break;
kono
parents:
diff changeset
1147 }
kono
parents:
diff changeset
1148 if (j < 0)
kono
parents:
diff changeset
1149 continue;
kono
parents:
diff changeset
1150 }
kono
parents:
diff changeset
1151 else
kono
parents:
diff changeset
1152 continue;
kono
parents:
diff changeset
1153 operand->type = OP_OUT;
kono
parents:
diff changeset
1154 }
kono
parents:
diff changeset
1155 return data;
kono
parents:
diff changeset
1156 }
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 /* Return info about insn give by UID. The info should be already set
kono
parents:
diff changeset
1159 up. */
kono
parents:
diff changeset
1160 static lra_insn_recog_data_t
kono
parents:
diff changeset
1161 get_insn_recog_data_by_uid (int uid)
kono
parents:
diff changeset
1162 {
kono
parents:
diff changeset
1163 lra_insn_recog_data_t data;
kono
parents:
diff changeset
1164
kono
parents:
diff changeset
1165 data = lra_insn_recog_data[uid];
kono
parents:
diff changeset
1166 lra_assert (data != NULL);
kono
parents:
diff changeset
1167 return data;
kono
parents:
diff changeset
1168 }
kono
parents:
diff changeset
1169
kono
parents:
diff changeset
1170 /* Invalidate all info about insn given by its UID. */
kono
parents:
diff changeset
1171 static void
kono
parents:
diff changeset
1172 invalidate_insn_recog_data (int uid)
kono
parents:
diff changeset
1173 {
kono
parents:
diff changeset
1174 lra_insn_recog_data_t data;
kono
parents:
diff changeset
1175
kono
parents:
diff changeset
1176 data = lra_insn_recog_data[uid];
kono
parents:
diff changeset
1177 lra_assert (data != NULL);
kono
parents:
diff changeset
1178 free_insn_recog_data (data);
kono
parents:
diff changeset
1179 lra_insn_recog_data[uid] = NULL;
kono
parents:
diff changeset
1180 }
kono
parents:
diff changeset
1181
kono
parents:
diff changeset
1182 /* Update all the insn info about INSN. It is usually called when
kono
parents:
diff changeset
1183 something in the insn was changed. Return the updated info. */
kono
parents:
diff changeset
1184 lra_insn_recog_data_t
kono
parents:
diff changeset
1185 lra_update_insn_recog_data (rtx_insn *insn)
kono
parents:
diff changeset
1186 {
kono
parents:
diff changeset
1187 lra_insn_recog_data_t data;
kono
parents:
diff changeset
1188 int n;
kono
parents:
diff changeset
1189 unsigned int uid = INSN_UID (insn);
kono
parents:
diff changeset
1190 struct lra_static_insn_data *insn_static_data;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1191 poly_int64 sp_offset = 0;
111
kono
parents:
diff changeset
1192
kono
parents:
diff changeset
1193 check_and_expand_insn_recog_data (uid);
kono
parents:
diff changeset
1194 if ((data = lra_insn_recog_data[uid]) != NULL
kono
parents:
diff changeset
1195 && data->icode != INSN_CODE (insn))
kono
parents:
diff changeset
1196 {
kono
parents:
diff changeset
1197 sp_offset = data->sp_offset;
kono
parents:
diff changeset
1198 invalidate_insn_data_regno_info (data, insn, get_insn_freq (insn));
kono
parents:
diff changeset
1199 invalidate_insn_recog_data (uid);
kono
parents:
diff changeset
1200 data = NULL;
kono
parents:
diff changeset
1201 }
kono
parents:
diff changeset
1202 if (data == NULL)
kono
parents:
diff changeset
1203 {
kono
parents:
diff changeset
1204 data = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
1205 /* Initiate or restore SP offset. */
kono
parents:
diff changeset
1206 data->sp_offset = sp_offset;
kono
parents:
diff changeset
1207 return data;
kono
parents:
diff changeset
1208 }
kono
parents:
diff changeset
1209 insn_static_data = data->insn_static_data;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1210 data->used_insn_alternative = LRA_UNKNOWN_ALT;
111
kono
parents:
diff changeset
1211 if (DEBUG_INSN_P (insn))
kono
parents:
diff changeset
1212 return data;
kono
parents:
diff changeset
1213 if (data->icode < 0)
kono
parents:
diff changeset
1214 {
kono
parents:
diff changeset
1215 int nop;
kono
parents:
diff changeset
1216 machine_mode operand_mode[MAX_RECOG_OPERANDS];
kono
parents:
diff changeset
1217 const char *constraints[MAX_RECOG_OPERANDS];
kono
parents:
diff changeset
1218
kono
parents:
diff changeset
1219 nop = asm_noperands (PATTERN (insn));
kono
parents:
diff changeset
1220 if (nop >= 0)
kono
parents:
diff changeset
1221 {
kono
parents:
diff changeset
1222 lra_assert (nop == data->insn_static_data->n_operands);
kono
parents:
diff changeset
1223 /* Now get the operand values and constraints out of the
kono
parents:
diff changeset
1224 insn. */
kono
parents:
diff changeset
1225 decode_asm_operands (PATTERN (insn), NULL,
kono
parents:
diff changeset
1226 data->operand_loc,
kono
parents:
diff changeset
1227 constraints, operand_mode, NULL);
kono
parents:
diff changeset
1228
kono
parents:
diff changeset
1229 if (flag_checking)
kono
parents:
diff changeset
1230 for (int i = 0; i < nop; i++)
kono
parents:
diff changeset
1231 lra_assert
kono
parents:
diff changeset
1232 (insn_static_data->operand[i].mode == operand_mode[i]
kono
parents:
diff changeset
1233 && insn_static_data->operand[i].constraint == constraints[i]
kono
parents:
diff changeset
1234 && ! insn_static_data->operand[i].is_operator);
kono
parents:
diff changeset
1235 }
kono
parents:
diff changeset
1236
kono
parents:
diff changeset
1237 if (flag_checking)
kono
parents:
diff changeset
1238 for (int i = 0; i < insn_static_data->n_operands; i++)
kono
parents:
diff changeset
1239 lra_assert
kono
parents:
diff changeset
1240 (insn_static_data->operand[i].type
kono
parents:
diff changeset
1241 == (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
kono
parents:
diff changeset
1242 : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
kono
parents:
diff changeset
1243 : OP_IN));
kono
parents:
diff changeset
1244 }
kono
parents:
diff changeset
1245 else
kono
parents:
diff changeset
1246 {
kono
parents:
diff changeset
1247 insn_extract (insn);
kono
parents:
diff changeset
1248 n = insn_static_data->n_operands;
kono
parents:
diff changeset
1249 if (n != 0)
kono
parents:
diff changeset
1250 memcpy (data->operand_loc, recog_data.operand_loc, n * sizeof (rtx *));
kono
parents:
diff changeset
1251 n = insn_static_data->n_dups;
kono
parents:
diff changeset
1252 if (n != 0)
kono
parents:
diff changeset
1253 memcpy (data->dup_loc, recog_data.dup_loc, n * sizeof (rtx *));
kono
parents:
diff changeset
1254 lra_assert (check_bool_attrs (insn));
kono
parents:
diff changeset
1255 }
kono
parents:
diff changeset
1256 return data;
kono
parents:
diff changeset
1257 }
kono
parents:
diff changeset
1258
kono
parents:
diff changeset
1259 /* Set up that INSN is using alternative ALT now. */
kono
parents:
diff changeset
1260 void
kono
parents:
diff changeset
1261 lra_set_used_insn_alternative (rtx_insn *insn, int alt)
kono
parents:
diff changeset
1262 {
kono
parents:
diff changeset
1263 lra_insn_recog_data_t data;
kono
parents:
diff changeset
1264
kono
parents:
diff changeset
1265 data = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
1266 data->used_insn_alternative = alt;
kono
parents:
diff changeset
1267 }
kono
parents:
diff changeset
1268
kono
parents:
diff changeset
1269 /* Set up that insn with UID is using alternative ALT now. The insn
kono
parents:
diff changeset
1270 info should be already set up. */
kono
parents:
diff changeset
1271 void
kono
parents:
diff changeset
1272 lra_set_used_insn_alternative_by_uid (int uid, int alt)
kono
parents:
diff changeset
1273 {
kono
parents:
diff changeset
1274 lra_insn_recog_data_t data;
kono
parents:
diff changeset
1275
kono
parents:
diff changeset
1276 check_and_expand_insn_recog_data (uid);
kono
parents:
diff changeset
1277 data = lra_insn_recog_data[uid];
kono
parents:
diff changeset
1278 lra_assert (data != NULL);
kono
parents:
diff changeset
1279 data->used_insn_alternative = alt;
kono
parents:
diff changeset
1280 }
kono
parents:
diff changeset
1281
kono
parents:
diff changeset
1282
kono
parents:
diff changeset
1283
kono
parents:
diff changeset
1284 /* This page contains code dealing with common register info and
kono
parents:
diff changeset
1285 pseudo copies. */
kono
parents:
diff changeset
1286
kono
parents:
diff changeset
1287 /* The size of the following array. */
kono
parents:
diff changeset
1288 static int reg_info_size;
kono
parents:
diff changeset
1289 /* Common info about each register. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1290 class lra_reg *lra_reg_info;
111
kono
parents:
diff changeset
1291
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1292 HARD_REG_SET hard_regs_spilled_into;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1293
111
kono
parents:
diff changeset
1294 /* Last register value. */
kono
parents:
diff changeset
1295 static int last_reg_value;
kono
parents:
diff changeset
1296
kono
parents:
diff changeset
1297 /* Return new register value. */
kono
parents:
diff changeset
1298 static int
kono
parents:
diff changeset
1299 get_new_reg_value (void)
kono
parents:
diff changeset
1300 {
kono
parents:
diff changeset
1301 return ++last_reg_value;
kono
parents:
diff changeset
1302 }
kono
parents:
diff changeset
1303
kono
parents:
diff changeset
1304 /* Vec referring to pseudo copies. */
kono
parents:
diff changeset
1305 static vec<lra_copy_t> copy_vec;
kono
parents:
diff changeset
1306
kono
parents:
diff changeset
1307 /* Initialize I-th element of lra_reg_info. */
kono
parents:
diff changeset
1308 static inline void
kono
parents:
diff changeset
1309 initialize_lra_reg_info_element (int i)
kono
parents:
diff changeset
1310 {
kono
parents:
diff changeset
1311 bitmap_initialize (&lra_reg_info[i].insn_bitmap, &reg_obstack);
kono
parents:
diff changeset
1312 #ifdef STACK_REGS
kono
parents:
diff changeset
1313 lra_reg_info[i].no_stack_p = false;
kono
parents:
diff changeset
1314 #endif
kono
parents:
diff changeset
1315 CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
kono
parents:
diff changeset
1316 lra_reg_info[i].preferred_hard_regno1 = -1;
kono
parents:
diff changeset
1317 lra_reg_info[i].preferred_hard_regno2 = -1;
kono
parents:
diff changeset
1318 lra_reg_info[i].preferred_hard_regno_profit1 = 0;
kono
parents:
diff changeset
1319 lra_reg_info[i].preferred_hard_regno_profit2 = 0;
kono
parents:
diff changeset
1320 lra_reg_info[i].biggest_mode = VOIDmode;
kono
parents:
diff changeset
1321 lra_reg_info[i].live_ranges = NULL;
kono
parents:
diff changeset
1322 lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0;
kono
parents:
diff changeset
1323 lra_reg_info[i].last_reload = 0;
kono
parents:
diff changeset
1324 lra_reg_info[i].restore_rtx = NULL_RTX;
kono
parents:
diff changeset
1325 lra_reg_info[i].val = get_new_reg_value ();
kono
parents:
diff changeset
1326 lra_reg_info[i].offset = 0;
kono
parents:
diff changeset
1327 lra_reg_info[i].copies = NULL;
kono
parents:
diff changeset
1328 }
kono
parents:
diff changeset
1329
kono
parents:
diff changeset
1330 /* Initialize common reg info and copies. */
kono
parents:
diff changeset
1331 static void
kono
parents:
diff changeset
1332 init_reg_info (void)
kono
parents:
diff changeset
1333 {
kono
parents:
diff changeset
1334 int i;
kono
parents:
diff changeset
1335
kono
parents:
diff changeset
1336 last_reg_value = 0;
kono
parents:
diff changeset
1337 reg_info_size = max_reg_num () * 3 / 2 + 1;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1338 lra_reg_info = XNEWVEC (class lra_reg, reg_info_size);
111
kono
parents:
diff changeset
1339 for (i = 0; i < reg_info_size; i++)
kono
parents:
diff changeset
1340 initialize_lra_reg_info_element (i);
kono
parents:
diff changeset
1341 copy_vec.truncate (0);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1342 CLEAR_HARD_REG_SET (hard_regs_spilled_into);
111
kono
parents:
diff changeset
1343 }
kono
parents:
diff changeset
1344
kono
parents:
diff changeset
1345
kono
parents:
diff changeset
1346 /* Finish common reg info and copies. */
kono
parents:
diff changeset
1347 static void
kono
parents:
diff changeset
1348 finish_reg_info (void)
kono
parents:
diff changeset
1349 {
kono
parents:
diff changeset
1350 int i;
kono
parents:
diff changeset
1351
kono
parents:
diff changeset
1352 for (i = 0; i < reg_info_size; i++)
kono
parents:
diff changeset
1353 bitmap_clear (&lra_reg_info[i].insn_bitmap);
kono
parents:
diff changeset
1354 free (lra_reg_info);
kono
parents:
diff changeset
1355 reg_info_size = 0;
kono
parents:
diff changeset
1356 }
kono
parents:
diff changeset
1357
kono
parents:
diff changeset
1358 /* Expand common reg info if it is necessary. */
kono
parents:
diff changeset
1359 static void
kono
parents:
diff changeset
1360 expand_reg_info (void)
kono
parents:
diff changeset
1361 {
kono
parents:
diff changeset
1362 int i, old = reg_info_size;
kono
parents:
diff changeset
1363
kono
parents:
diff changeset
1364 if (reg_info_size > max_reg_num ())
kono
parents:
diff changeset
1365 return;
kono
parents:
diff changeset
1366 reg_info_size = max_reg_num () * 3 / 2 + 1;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1367 lra_reg_info = XRESIZEVEC (class lra_reg, lra_reg_info, reg_info_size);
111
kono
parents:
diff changeset
1368 for (i = old; i < reg_info_size; i++)
kono
parents:
diff changeset
1369 initialize_lra_reg_info_element (i);
kono
parents:
diff changeset
1370 }
kono
parents:
diff changeset
1371
kono
parents:
diff changeset
1372 /* Free all copies. */
kono
parents:
diff changeset
1373 void
kono
parents:
diff changeset
1374 lra_free_copies (void)
kono
parents:
diff changeset
1375 {
kono
parents:
diff changeset
1376 lra_copy_t cp;
kono
parents:
diff changeset
1377
kono
parents:
diff changeset
1378 while (copy_vec.length () != 0)
kono
parents:
diff changeset
1379 {
kono
parents:
diff changeset
1380 cp = copy_vec.pop ();
kono
parents:
diff changeset
1381 lra_reg_info[cp->regno1].copies = lra_reg_info[cp->regno2].copies = NULL;
kono
parents:
diff changeset
1382 lra_copy_pool.remove (cp);
kono
parents:
diff changeset
1383 }
kono
parents:
diff changeset
1384 }
kono
parents:
diff changeset
1385
kono
parents:
diff changeset
1386 /* Create copy of two pseudos REGNO1 and REGNO2. The copy execution
kono
parents:
diff changeset
1387 frequency is FREQ. */
kono
parents:
diff changeset
1388 void
kono
parents:
diff changeset
1389 lra_create_copy (int regno1, int regno2, int freq)
kono
parents:
diff changeset
1390 {
kono
parents:
diff changeset
1391 bool regno1_dest_p;
kono
parents:
diff changeset
1392 lra_copy_t cp;
kono
parents:
diff changeset
1393
kono
parents:
diff changeset
1394 lra_assert (regno1 != regno2);
kono
parents:
diff changeset
1395 regno1_dest_p = true;
kono
parents:
diff changeset
1396 if (regno1 > regno2)
kono
parents:
diff changeset
1397 {
kono
parents:
diff changeset
1398 std::swap (regno1, regno2);
kono
parents:
diff changeset
1399 regno1_dest_p = false;
kono
parents:
diff changeset
1400 }
kono
parents:
diff changeset
1401 cp = lra_copy_pool.allocate ();
kono
parents:
diff changeset
1402 copy_vec.safe_push (cp);
kono
parents:
diff changeset
1403 cp->regno1_dest_p = regno1_dest_p;
kono
parents:
diff changeset
1404 cp->freq = freq;
kono
parents:
diff changeset
1405 cp->regno1 = regno1;
kono
parents:
diff changeset
1406 cp->regno2 = regno2;
kono
parents:
diff changeset
1407 cp->regno1_next = lra_reg_info[regno1].copies;
kono
parents:
diff changeset
1408 lra_reg_info[regno1].copies = cp;
kono
parents:
diff changeset
1409 cp->regno2_next = lra_reg_info[regno2].copies;
kono
parents:
diff changeset
1410 lra_reg_info[regno2].copies = cp;
kono
parents:
diff changeset
1411 if (lra_dump_file != NULL)
kono
parents:
diff changeset
1412 fprintf (lra_dump_file, " Creating copy r%d%sr%d@%d\n",
kono
parents:
diff changeset
1413 regno1, regno1_dest_p ? "<-" : "->", regno2, freq);
kono
parents:
diff changeset
1414 }
kono
parents:
diff changeset
1415
kono
parents:
diff changeset
1416 /* Return N-th (0, 1, ...) copy. If there is no copy, return
kono
parents:
diff changeset
1417 NULL. */
kono
parents:
diff changeset
1418 lra_copy_t
kono
parents:
diff changeset
1419 lra_get_copy (int n)
kono
parents:
diff changeset
1420 {
kono
parents:
diff changeset
1421 if (n >= (int) copy_vec.length ())
kono
parents:
diff changeset
1422 return NULL;
kono
parents:
diff changeset
1423 return copy_vec[n];
kono
parents:
diff changeset
1424 }
kono
parents:
diff changeset
1425
kono
parents:
diff changeset
1426
kono
parents:
diff changeset
1427
kono
parents:
diff changeset
1428 /* This page contains code dealing with info about registers in
kono
parents:
diff changeset
1429 insns. */
kono
parents:
diff changeset
1430
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1431 /* Process X of INSN recursively and add info (operand type is given
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1432 by TYPE) about registers in X to the insn DATA. If X can be early
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1433 clobbered, alternatives in which it can be early clobbered are given
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1434 by EARLY_CLOBBER_ALTS. */
111
kono
parents:
diff changeset
1435 static void
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1436 add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1437 rtx_insn *insn, enum op_type type,
111
kono
parents:
diff changeset
1438 alternative_mask early_clobber_alts)
kono
parents:
diff changeset
1439 {
kono
parents:
diff changeset
1440 int i, j, regno;
kono
parents:
diff changeset
1441 bool subreg_p;
kono
parents:
diff changeset
1442 machine_mode mode;
kono
parents:
diff changeset
1443 const char *fmt;
kono
parents:
diff changeset
1444 enum rtx_code code;
kono
parents:
diff changeset
1445 struct lra_insn_reg *curr;
kono
parents:
diff changeset
1446
kono
parents:
diff changeset
1447 code = GET_CODE (x);
kono
parents:
diff changeset
1448 mode = GET_MODE (x);
kono
parents:
diff changeset
1449 subreg_p = false;
kono
parents:
diff changeset
1450 if (GET_CODE (x) == SUBREG)
kono
parents:
diff changeset
1451 {
kono
parents:
diff changeset
1452 mode = wider_subreg_mode (x);
kono
parents:
diff changeset
1453 if (read_modify_subreg_p (x))
kono
parents:
diff changeset
1454 subreg_p = true;
kono
parents:
diff changeset
1455 x = SUBREG_REG (x);
kono
parents:
diff changeset
1456 code = GET_CODE (x);
kono
parents:
diff changeset
1457 }
kono
parents:
diff changeset
1458 if (REG_P (x))
kono
parents:
diff changeset
1459 {
kono
parents:
diff changeset
1460 regno = REGNO (x);
kono
parents:
diff changeset
1461 /* Process all regs even unallocatable ones as we need info about
kono
parents:
diff changeset
1462 all regs for rematerialization pass. */
kono
parents:
diff changeset
1463 expand_reg_info ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1464 if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, INSN_UID (insn)))
111
kono
parents:
diff changeset
1465 {
kono
parents:
diff changeset
1466 data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1467 early_clobber_alts, data->regs);
111
kono
parents:
diff changeset
1468 return;
kono
parents:
diff changeset
1469 }
kono
parents:
diff changeset
1470 else
kono
parents:
diff changeset
1471 {
kono
parents:
diff changeset
1472 for (curr = data->regs; curr != NULL; curr = curr->next)
kono
parents:
diff changeset
1473 if (curr->regno == regno)
kono
parents:
diff changeset
1474 {
kono
parents:
diff changeset
1475 if (curr->subreg_p != subreg_p || curr->biggest_mode != mode)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1476 /* The info cannot be integrated into the found
111
kono
parents:
diff changeset
1477 structure. */
kono
parents:
diff changeset
1478 data->regs = new_insn_reg (data->insn, regno, type, mode,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1479 subreg_p, early_clobber_alts,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1480 data->regs);
111
kono
parents:
diff changeset
1481 else
kono
parents:
diff changeset
1482 {
kono
parents:
diff changeset
1483 if (curr->type != type)
kono
parents:
diff changeset
1484 curr->type = OP_INOUT;
kono
parents:
diff changeset
1485 curr->early_clobber_alts |= early_clobber_alts;
kono
parents:
diff changeset
1486 }
kono
parents:
diff changeset
1487 return;
kono
parents:
diff changeset
1488 }
kono
parents:
diff changeset
1489 gcc_unreachable ();
kono
parents:
diff changeset
1490 }
kono
parents:
diff changeset
1491 }
kono
parents:
diff changeset
1492
kono
parents:
diff changeset
1493 switch (code)
kono
parents:
diff changeset
1494 {
kono
parents:
diff changeset
1495 case SET:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1496 add_regs_to_insn_regno_info (data, SET_DEST (x), insn, OP_OUT, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1497 add_regs_to_insn_regno_info (data, SET_SRC (x), insn, OP_IN, 0);
111
kono
parents:
diff changeset
1498 break;
kono
parents:
diff changeset
1499 case CLOBBER:
kono
parents:
diff changeset
1500 /* We treat clobber of non-operand hard registers as early
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1501 clobber. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1502 add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_OUT,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1503 ALL_ALTERNATIVES);
111
kono
parents:
diff changeset
1504 break;
kono
parents:
diff changeset
1505 case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1506 add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, 0);
111
kono
parents:
diff changeset
1507 break;
kono
parents:
diff changeset
1508 case PRE_MODIFY: case POST_MODIFY:
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1509 add_regs_to_insn_regno_info (data, XEXP (x, 0), insn, OP_INOUT, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1510 add_regs_to_insn_regno_info (data, XEXP (x, 1), insn, OP_IN, 0);
111
kono
parents:
diff changeset
1511 break;
kono
parents:
diff changeset
1512 default:
kono
parents:
diff changeset
1513 if ((code != PARALLEL && code != EXPR_LIST) || type != OP_OUT)
kono
parents:
diff changeset
1514 /* Some targets place small structures in registers for return
kono
parents:
diff changeset
1515 values of functions, and those registers are wrapped in
kono
parents:
diff changeset
1516 PARALLEL that we may see as the destination of a SET. Here
kono
parents:
diff changeset
1517 is an example:
kono
parents:
diff changeset
1518
kono
parents:
diff changeset
1519 (call_insn 13 12 14 2 (set (parallel:BLK [
kono
parents:
diff changeset
1520 (expr_list:REG_DEP_TRUE (reg:DI 0 ax)
kono
parents:
diff changeset
1521 (const_int 0 [0]))
kono
parents:
diff changeset
1522 (expr_list:REG_DEP_TRUE (reg:DI 1 dx)
kono
parents:
diff changeset
1523 (const_int 8 [0x8]))
kono
parents:
diff changeset
1524 ])
kono
parents:
diff changeset
1525 (call (mem:QI (symbol_ref:DI (... */
kono
parents:
diff changeset
1526 type = OP_IN;
kono
parents:
diff changeset
1527 fmt = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
1528 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
kono
parents:
diff changeset
1529 {
kono
parents:
diff changeset
1530 if (fmt[i] == 'e')
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1531 add_regs_to_insn_regno_info (data, XEXP (x, i), insn, type, 0);
111
kono
parents:
diff changeset
1532 else if (fmt[i] == 'E')
kono
parents:
diff changeset
1533 {
kono
parents:
diff changeset
1534 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1535 add_regs_to_insn_regno_info (data, XVECEXP (x, i, j), insn,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1536 type, 0);
111
kono
parents:
diff changeset
1537 }
kono
parents:
diff changeset
1538 }
kono
parents:
diff changeset
1539 }
kono
parents:
diff changeset
1540 }
kono
parents:
diff changeset
1541
kono
parents:
diff changeset
1542 /* Return execution frequency of INSN. */
kono
parents:
diff changeset
1543 static int
kono
parents:
diff changeset
1544 get_insn_freq (rtx_insn *insn)
kono
parents:
diff changeset
1545 {
kono
parents:
diff changeset
1546 basic_block bb = BLOCK_FOR_INSN (insn);
kono
parents:
diff changeset
1547
kono
parents:
diff changeset
1548 gcc_checking_assert (bb != NULL);
kono
parents:
diff changeset
1549 return REG_FREQ_FROM_BB (bb);
kono
parents:
diff changeset
1550 }
kono
parents:
diff changeset
1551
kono
parents:
diff changeset
1552 /* Invalidate all reg info of INSN with DATA and execution frequency
kono
parents:
diff changeset
1553 FREQ. Update common info about the invalidated registers. */
kono
parents:
diff changeset
1554 static void
kono
parents:
diff changeset
1555 invalidate_insn_data_regno_info (lra_insn_recog_data_t data, rtx_insn *insn,
kono
parents:
diff changeset
1556 int freq)
kono
parents:
diff changeset
1557 {
kono
parents:
diff changeset
1558 int uid;
kono
parents:
diff changeset
1559 bool debug_p;
kono
parents:
diff changeset
1560 unsigned int i;
kono
parents:
diff changeset
1561 struct lra_insn_reg *ir, *next_ir;
kono
parents:
diff changeset
1562
kono
parents:
diff changeset
1563 uid = INSN_UID (insn);
kono
parents:
diff changeset
1564 debug_p = DEBUG_INSN_P (insn);
kono
parents:
diff changeset
1565 for (ir = data->regs; ir != NULL; ir = next_ir)
kono
parents:
diff changeset
1566 {
kono
parents:
diff changeset
1567 i = ir->regno;
kono
parents:
diff changeset
1568 next_ir = ir->next;
kono
parents:
diff changeset
1569 lra_insn_reg_pool.remove (ir);
kono
parents:
diff changeset
1570 bitmap_clear_bit (&lra_reg_info[i].insn_bitmap, uid);
kono
parents:
diff changeset
1571 if (i >= FIRST_PSEUDO_REGISTER && ! debug_p)
kono
parents:
diff changeset
1572 {
kono
parents:
diff changeset
1573 lra_reg_info[i].nrefs--;
kono
parents:
diff changeset
1574 lra_reg_info[i].freq -= freq;
kono
parents:
diff changeset
1575 lra_assert (lra_reg_info[i].nrefs >= 0 && lra_reg_info[i].freq >= 0);
kono
parents:
diff changeset
1576 }
kono
parents:
diff changeset
1577 }
kono
parents:
diff changeset
1578 data->regs = NULL;
kono
parents:
diff changeset
1579 }
kono
parents:
diff changeset
1580
kono
parents:
diff changeset
1581 /* Invalidate all reg info of INSN. Update common info about the
kono
parents:
diff changeset
1582 invalidated registers. */
kono
parents:
diff changeset
1583 void
kono
parents:
diff changeset
1584 lra_invalidate_insn_regno_info (rtx_insn *insn)
kono
parents:
diff changeset
1585 {
kono
parents:
diff changeset
1586 invalidate_insn_data_regno_info (lra_get_insn_recog_data (insn), insn,
kono
parents:
diff changeset
1587 get_insn_freq (insn));
kono
parents:
diff changeset
1588 }
kono
parents:
diff changeset
1589
kono
parents:
diff changeset
1590 /* Update common reg info from reg info of insn given by its DATA and
kono
parents:
diff changeset
1591 execution frequency FREQ. */
kono
parents:
diff changeset
1592 static void
kono
parents:
diff changeset
1593 setup_insn_reg_info (lra_insn_recog_data_t data, int freq)
kono
parents:
diff changeset
1594 {
kono
parents:
diff changeset
1595 unsigned int i;
kono
parents:
diff changeset
1596 struct lra_insn_reg *ir;
kono
parents:
diff changeset
1597
kono
parents:
diff changeset
1598 for (ir = data->regs; ir != NULL; ir = ir->next)
kono
parents:
diff changeset
1599 if ((i = ir->regno) >= FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
1600 {
kono
parents:
diff changeset
1601 lra_reg_info[i].nrefs++;
kono
parents:
diff changeset
1602 lra_reg_info[i].freq += freq;
kono
parents:
diff changeset
1603 }
kono
parents:
diff changeset
1604 }
kono
parents:
diff changeset
1605
kono
parents:
diff changeset
1606 /* Set up insn reg info of INSN. Update common reg info from reg info
kono
parents:
diff changeset
1607 of INSN. */
kono
parents:
diff changeset
1608 void
kono
parents:
diff changeset
1609 lra_update_insn_regno_info (rtx_insn *insn)
kono
parents:
diff changeset
1610 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1611 int i, freq;
111
kono
parents:
diff changeset
1612 lra_insn_recog_data_t data;
kono
parents:
diff changeset
1613 struct lra_static_insn_data *static_data;
kono
parents:
diff changeset
1614 enum rtx_code code;
kono
parents:
diff changeset
1615 rtx link;
kono
parents:
diff changeset
1616
kono
parents:
diff changeset
1617 if (! INSN_P (insn))
kono
parents:
diff changeset
1618 return;
kono
parents:
diff changeset
1619 data = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
1620 static_data = data->insn_static_data;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1621 freq = NONDEBUG_INSN_P (insn) ? get_insn_freq (insn) : 0;
111
kono
parents:
diff changeset
1622 invalidate_insn_data_regno_info (data, insn, freq);
kono
parents:
diff changeset
1623 for (i = static_data->n_operands - 1; i >= 0; i--)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1624 add_regs_to_insn_regno_info (data, *data->operand_loc[i], insn,
111
kono
parents:
diff changeset
1625 static_data->operand[i].type,
kono
parents:
diff changeset
1626 static_data->operand[i].early_clobber_alts);
kono
parents:
diff changeset
1627 if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1628 add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), insn,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1629 code == USE ? OP_IN : OP_OUT, 0);
111
kono
parents:
diff changeset
1630 if (CALL_P (insn))
kono
parents:
diff changeset
1631 /* On some targets call insns can refer to pseudos in memory in
kono
parents:
diff changeset
1632 CALL_INSN_FUNCTION_USAGE list. Process them in order to
kono
parents:
diff changeset
1633 consider their occurrences in calls for different
kono
parents:
diff changeset
1634 transformations (e.g. inheritance) with given pseudos. */
kono
parents:
diff changeset
1635 for (link = CALL_INSN_FUNCTION_USAGE (insn);
kono
parents:
diff changeset
1636 link != NULL_RTX;
kono
parents:
diff changeset
1637 link = XEXP (link, 1))
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1638 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1639 code = GET_CODE (XEXP (link, 0));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1640 if ((code == USE || code == CLOBBER)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1641 && MEM_P (XEXP (XEXP (link, 0), 0)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1642 add_regs_to_insn_regno_info (data, XEXP (XEXP (link, 0), 0), insn,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1643 code == USE ? OP_IN : OP_OUT, 0);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1644 }
111
kono
parents:
diff changeset
1645 if (NONDEBUG_INSN_P (insn))
kono
parents:
diff changeset
1646 setup_insn_reg_info (data, freq);
kono
parents:
diff changeset
1647 }
kono
parents:
diff changeset
1648
kono
parents:
diff changeset
1649 /* Return reg info of insn given by it UID. */
kono
parents:
diff changeset
1650 struct lra_insn_reg *
kono
parents:
diff changeset
1651 lra_get_insn_regs (int uid)
kono
parents:
diff changeset
1652 {
kono
parents:
diff changeset
1653 lra_insn_recog_data_t data;
kono
parents:
diff changeset
1654
kono
parents:
diff changeset
1655 data = get_insn_recog_data_by_uid (uid);
kono
parents:
diff changeset
1656 return data->regs;
kono
parents:
diff changeset
1657 }
kono
parents:
diff changeset
1658
kono
parents:
diff changeset
1659
kono
parents:
diff changeset
1660
kono
parents:
diff changeset
1661 /* Recursive hash function for RTL X. */
kono
parents:
diff changeset
1662 hashval_t
kono
parents:
diff changeset
1663 lra_rtx_hash (rtx x)
kono
parents:
diff changeset
1664 {
kono
parents:
diff changeset
1665 int i, j;
kono
parents:
diff changeset
1666 enum rtx_code code;
kono
parents:
diff changeset
1667 const char *fmt;
kono
parents:
diff changeset
1668 hashval_t val = 0;
kono
parents:
diff changeset
1669
kono
parents:
diff changeset
1670 if (x == 0)
kono
parents:
diff changeset
1671 return val;
kono
parents:
diff changeset
1672
kono
parents:
diff changeset
1673 code = GET_CODE (x);
kono
parents:
diff changeset
1674 val += (int) code + 4095;
kono
parents:
diff changeset
1675
kono
parents:
diff changeset
1676 /* Some RTL can be compared nonrecursively. */
kono
parents:
diff changeset
1677 switch (code)
kono
parents:
diff changeset
1678 {
kono
parents:
diff changeset
1679 case REG:
kono
parents:
diff changeset
1680 return val + REGNO (x);
kono
parents:
diff changeset
1681
kono
parents:
diff changeset
1682 case LABEL_REF:
kono
parents:
diff changeset
1683 return iterative_hash_object (XEXP (x, 0), val);
kono
parents:
diff changeset
1684
kono
parents:
diff changeset
1685 case SYMBOL_REF:
kono
parents:
diff changeset
1686 return iterative_hash_object (XSTR (x, 0), val);
kono
parents:
diff changeset
1687
kono
parents:
diff changeset
1688 case SCRATCH:
kono
parents:
diff changeset
1689 case CONST_DOUBLE:
kono
parents:
diff changeset
1690 case CONST_VECTOR:
kono
parents:
diff changeset
1691 return val;
kono
parents:
diff changeset
1692
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1693 case CONST_INT:
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1694 return val + UINTVAL (x);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1695
111
kono
parents:
diff changeset
1696 default:
kono
parents:
diff changeset
1697 break;
kono
parents:
diff changeset
1698 }
kono
parents:
diff changeset
1699
kono
parents:
diff changeset
1700 /* Hash the elements. */
kono
parents:
diff changeset
1701 fmt = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
1702 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
kono
parents:
diff changeset
1703 {
kono
parents:
diff changeset
1704 switch (fmt[i])
kono
parents:
diff changeset
1705 {
kono
parents:
diff changeset
1706 case 'w':
kono
parents:
diff changeset
1707 val += XWINT (x, i);
kono
parents:
diff changeset
1708 break;
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 case 'n':
kono
parents:
diff changeset
1711 case 'i':
kono
parents:
diff changeset
1712 val += XINT (x, i);
kono
parents:
diff changeset
1713 break;
kono
parents:
diff changeset
1714
kono
parents:
diff changeset
1715 case 'V':
kono
parents:
diff changeset
1716 case 'E':
kono
parents:
diff changeset
1717 val += XVECLEN (x, i);
kono
parents:
diff changeset
1718
kono
parents:
diff changeset
1719 for (j = 0; j < XVECLEN (x, i); j++)
kono
parents:
diff changeset
1720 val += lra_rtx_hash (XVECEXP (x, i, j));
kono
parents:
diff changeset
1721 break;
kono
parents:
diff changeset
1722
kono
parents:
diff changeset
1723 case 'e':
kono
parents:
diff changeset
1724 val += lra_rtx_hash (XEXP (x, i));
kono
parents:
diff changeset
1725 break;
kono
parents:
diff changeset
1726
kono
parents:
diff changeset
1727 case 'S':
kono
parents:
diff changeset
1728 case 's':
kono
parents:
diff changeset
1729 val += htab_hash_string (XSTR (x, i));
kono
parents:
diff changeset
1730 break;
kono
parents:
diff changeset
1731
kono
parents:
diff changeset
1732 case 'u':
kono
parents:
diff changeset
1733 case '0':
kono
parents:
diff changeset
1734 case 't':
kono
parents:
diff changeset
1735 break;
kono
parents:
diff changeset
1736
kono
parents:
diff changeset
1737 /* It is believed that rtx's at this level will never
kono
parents:
diff changeset
1738 contain anything but integers and other rtx's, except for
kono
parents:
diff changeset
1739 within LABEL_REFs and SYMBOL_REFs. */
kono
parents:
diff changeset
1740 default:
kono
parents:
diff changeset
1741 abort ();
kono
parents:
diff changeset
1742 }
kono
parents:
diff changeset
1743 }
kono
parents:
diff changeset
1744 return val;
kono
parents:
diff changeset
1745 }
kono
parents:
diff changeset
1746
kono
parents:
diff changeset
1747
kono
parents:
diff changeset
1748
kono
parents:
diff changeset
1749 /* This page contains code dealing with stack of the insns which
kono
parents:
diff changeset
1750 should be processed by the next constraint pass. */
kono
parents:
diff changeset
1751
kono
parents:
diff changeset
1752 /* Bitmap used to put an insn on the stack only in one exemplar. */
kono
parents:
diff changeset
1753 static sbitmap lra_constraint_insn_stack_bitmap;
kono
parents:
diff changeset
1754
kono
parents:
diff changeset
1755 /* The stack itself. */
kono
parents:
diff changeset
1756 vec<rtx_insn *> lra_constraint_insn_stack;
kono
parents:
diff changeset
1757
kono
parents:
diff changeset
1758 /* Put INSN on the stack. If ALWAYS_UPDATE is true, always update the reg
kono
parents:
diff changeset
1759 info for INSN, otherwise only update it if INSN is not already on the
kono
parents:
diff changeset
1760 stack. */
kono
parents:
diff changeset
1761 static inline void
kono
parents:
diff changeset
1762 lra_push_insn_1 (rtx_insn *insn, bool always_update)
kono
parents:
diff changeset
1763 {
kono
parents:
diff changeset
1764 unsigned int uid = INSN_UID (insn);
kono
parents:
diff changeset
1765 if (always_update)
kono
parents:
diff changeset
1766 lra_update_insn_regno_info (insn);
kono
parents:
diff changeset
1767 if (uid >= SBITMAP_SIZE (lra_constraint_insn_stack_bitmap))
kono
parents:
diff changeset
1768 lra_constraint_insn_stack_bitmap =
kono
parents:
diff changeset
1769 sbitmap_resize (lra_constraint_insn_stack_bitmap, 3 * uid / 2, 0);
kono
parents:
diff changeset
1770 if (bitmap_bit_p (lra_constraint_insn_stack_bitmap, uid))
kono
parents:
diff changeset
1771 return;
kono
parents:
diff changeset
1772 bitmap_set_bit (lra_constraint_insn_stack_bitmap, uid);
kono
parents:
diff changeset
1773 if (! always_update)
kono
parents:
diff changeset
1774 lra_update_insn_regno_info (insn);
kono
parents:
diff changeset
1775 lra_constraint_insn_stack.safe_push (insn);
kono
parents:
diff changeset
1776 }
kono
parents:
diff changeset
1777
kono
parents:
diff changeset
1778 /* Put INSN on the stack. */
kono
parents:
diff changeset
1779 void
kono
parents:
diff changeset
1780 lra_push_insn (rtx_insn *insn)
kono
parents:
diff changeset
1781 {
kono
parents:
diff changeset
1782 lra_push_insn_1 (insn, false);
kono
parents:
diff changeset
1783 }
kono
parents:
diff changeset
1784
kono
parents:
diff changeset
1785 /* Put INSN on the stack and update its reg info. */
kono
parents:
diff changeset
1786 void
kono
parents:
diff changeset
1787 lra_push_insn_and_update_insn_regno_info (rtx_insn *insn)
kono
parents:
diff changeset
1788 {
kono
parents:
diff changeset
1789 lra_push_insn_1 (insn, true);
kono
parents:
diff changeset
1790 }
kono
parents:
diff changeset
1791
kono
parents:
diff changeset
1792 /* Put insn with UID on the stack. */
kono
parents:
diff changeset
1793 void
kono
parents:
diff changeset
1794 lra_push_insn_by_uid (unsigned int uid)
kono
parents:
diff changeset
1795 {
kono
parents:
diff changeset
1796 lra_push_insn (lra_insn_recog_data[uid]->insn);
kono
parents:
diff changeset
1797 }
kono
parents:
diff changeset
1798
kono
parents:
diff changeset
1799 /* Take the last-inserted insns off the stack and return it. */
kono
parents:
diff changeset
1800 rtx_insn *
kono
parents:
diff changeset
1801 lra_pop_insn (void)
kono
parents:
diff changeset
1802 {
kono
parents:
diff changeset
1803 rtx_insn *insn = lra_constraint_insn_stack.pop ();
kono
parents:
diff changeset
1804 bitmap_clear_bit (lra_constraint_insn_stack_bitmap, INSN_UID (insn));
kono
parents:
diff changeset
1805 return insn;
kono
parents:
diff changeset
1806 }
kono
parents:
diff changeset
1807
kono
parents:
diff changeset
1808 /* Return the current size of the insn stack. */
kono
parents:
diff changeset
1809 unsigned int
kono
parents:
diff changeset
1810 lra_insn_stack_length (void)
kono
parents:
diff changeset
1811 {
kono
parents:
diff changeset
1812 return lra_constraint_insn_stack.length ();
kono
parents:
diff changeset
1813 }
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 /* Push insns FROM to TO (excluding it) going in reverse order. */
kono
parents:
diff changeset
1816 static void
kono
parents:
diff changeset
1817 push_insns (rtx_insn *from, rtx_insn *to)
kono
parents:
diff changeset
1818 {
kono
parents:
diff changeset
1819 rtx_insn *insn;
kono
parents:
diff changeset
1820
kono
parents:
diff changeset
1821 if (from == NULL_RTX)
kono
parents:
diff changeset
1822 return;
kono
parents:
diff changeset
1823 for (insn = from; insn != to; insn = PREV_INSN (insn))
kono
parents:
diff changeset
1824 if (INSN_P (insn))
kono
parents:
diff changeset
1825 lra_push_insn (insn);
kono
parents:
diff changeset
1826 }
kono
parents:
diff changeset
1827
kono
parents:
diff changeset
1828 /* Set up sp offset for insn in range [FROM, LAST]. The offset is
kono
parents:
diff changeset
1829 taken from the next BB insn after LAST or zero if there in such
kono
parents:
diff changeset
1830 insn. */
kono
parents:
diff changeset
1831 static void
kono
parents:
diff changeset
1832 setup_sp_offset (rtx_insn *from, rtx_insn *last)
kono
parents:
diff changeset
1833 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1834 rtx_insn *before = next_nonnote_nondebug_insn_bb (last);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1835 poly_int64 offset = (before == NULL_RTX || ! INSN_P (before)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1836 ? 0 : lra_get_insn_recog_data (before)->sp_offset);
111
kono
parents:
diff changeset
1837
kono
parents:
diff changeset
1838 for (rtx_insn *insn = from; insn != NEXT_INSN (last); insn = NEXT_INSN (insn))
kono
parents:
diff changeset
1839 lra_get_insn_recog_data (insn)->sp_offset = offset;
kono
parents:
diff changeset
1840 }
kono
parents:
diff changeset
1841
kono
parents:
diff changeset
1842 /* Emit insns BEFORE before INSN and insns AFTER after INSN. Put the
kono
parents:
diff changeset
1843 insns onto the stack. Print about emitting the insns with
kono
parents:
diff changeset
1844 TITLE. */
kono
parents:
diff changeset
1845 void
kono
parents:
diff changeset
1846 lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
kono
parents:
diff changeset
1847 const char *title)
kono
parents:
diff changeset
1848 {
kono
parents:
diff changeset
1849 rtx_insn *last;
kono
parents:
diff changeset
1850
kono
parents:
diff changeset
1851 if (before == NULL_RTX && after == NULL_RTX)
kono
parents:
diff changeset
1852 return;
kono
parents:
diff changeset
1853 if (lra_dump_file != NULL)
kono
parents:
diff changeset
1854 {
kono
parents:
diff changeset
1855 dump_insn_slim (lra_dump_file, insn);
kono
parents:
diff changeset
1856 if (before != NULL_RTX)
kono
parents:
diff changeset
1857 {
kono
parents:
diff changeset
1858 fprintf (lra_dump_file," %s before:\n", title);
kono
parents:
diff changeset
1859 dump_rtl_slim (lra_dump_file, before, NULL, -1, 0);
kono
parents:
diff changeset
1860 }
kono
parents:
diff changeset
1861 if (after != NULL_RTX)
kono
parents:
diff changeset
1862 {
kono
parents:
diff changeset
1863 fprintf (lra_dump_file, " %s after:\n", title);
kono
parents:
diff changeset
1864 dump_rtl_slim (lra_dump_file, after, NULL, -1, 0);
kono
parents:
diff changeset
1865 }
kono
parents:
diff changeset
1866 fprintf (lra_dump_file, "\n");
kono
parents:
diff changeset
1867 }
kono
parents:
diff changeset
1868 if (before != NULL_RTX)
kono
parents:
diff changeset
1869 {
kono
parents:
diff changeset
1870 if (cfun->can_throw_non_call_exceptions)
kono
parents:
diff changeset
1871 copy_reg_eh_region_note_forward (insn, before, NULL);
kono
parents:
diff changeset
1872 emit_insn_before (before, insn);
kono
parents:
diff changeset
1873 push_insns (PREV_INSN (insn), PREV_INSN (before));
kono
parents:
diff changeset
1874 setup_sp_offset (before, PREV_INSN (insn));
kono
parents:
diff changeset
1875 }
kono
parents:
diff changeset
1876 if (after != NULL_RTX)
kono
parents:
diff changeset
1877 {
kono
parents:
diff changeset
1878 if (cfun->can_throw_non_call_exceptions)
kono
parents:
diff changeset
1879 copy_reg_eh_region_note_forward (insn, after, NULL);
kono
parents:
diff changeset
1880 for (last = after; NEXT_INSN (last) != NULL_RTX; last = NEXT_INSN (last))
kono
parents:
diff changeset
1881 ;
kono
parents:
diff changeset
1882 emit_insn_after (after, insn);
kono
parents:
diff changeset
1883 push_insns (last, insn);
kono
parents:
diff changeset
1884 setup_sp_offset (after, last);
kono
parents:
diff changeset
1885 }
kono
parents:
diff changeset
1886 if (cfun->can_throw_non_call_exceptions)
kono
parents:
diff changeset
1887 {
kono
parents:
diff changeset
1888 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
kono
parents:
diff changeset
1889 if (note && !insn_could_throw_p (insn))
kono
parents:
diff changeset
1890 remove_note (insn, note);
kono
parents:
diff changeset
1891 }
kono
parents:
diff changeset
1892 }
kono
parents:
diff changeset
1893
kono
parents:
diff changeset
1894
kono
parents:
diff changeset
1895 /* Replace all references to register OLD_REGNO in *LOC with pseudo
kono
parents:
diff changeset
1896 register NEW_REG. Try to simplify subreg of constant if SUBREG_P.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1897 DEBUG_P is if LOC is within a DEBUG_INSN. Return true if any
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1898 change was made. */
111
kono
parents:
diff changeset
1899 bool
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1900 lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg, bool subreg_p,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1901 bool debug_p)
111
kono
parents:
diff changeset
1902 {
kono
parents:
diff changeset
1903 rtx x = *loc;
kono
parents:
diff changeset
1904 bool result = false;
kono
parents:
diff changeset
1905 enum rtx_code code;
kono
parents:
diff changeset
1906 const char *fmt;
kono
parents:
diff changeset
1907 int i, j;
kono
parents:
diff changeset
1908
kono
parents:
diff changeset
1909 if (x == NULL_RTX)
kono
parents:
diff changeset
1910 return false;
kono
parents:
diff changeset
1911
kono
parents:
diff changeset
1912 code = GET_CODE (x);
kono
parents:
diff changeset
1913 if (code == SUBREG && subreg_p)
kono
parents:
diff changeset
1914 {
kono
parents:
diff changeset
1915 rtx subst, inner = SUBREG_REG (x);
kono
parents:
diff changeset
1916 /* Transform subreg of constant while we still have inner mode
kono
parents:
diff changeset
1917 of the subreg. The subreg internal should not be an insn
kono
parents:
diff changeset
1918 operand. */
kono
parents:
diff changeset
1919 if (REG_P (inner) && (int) REGNO (inner) == old_regno
kono
parents:
diff changeset
1920 && CONSTANT_P (new_reg)
kono
parents:
diff changeset
1921 && (subst = simplify_subreg (GET_MODE (x), new_reg, GET_MODE (inner),
kono
parents:
diff changeset
1922 SUBREG_BYTE (x))) != NULL_RTX)
kono
parents:
diff changeset
1923 {
kono
parents:
diff changeset
1924 *loc = subst;
kono
parents:
diff changeset
1925 return true;
kono
parents:
diff changeset
1926 }
kono
parents:
diff changeset
1927
kono
parents:
diff changeset
1928 }
kono
parents:
diff changeset
1929 else if (code == REG && (int) REGNO (x) == old_regno)
kono
parents:
diff changeset
1930 {
kono
parents:
diff changeset
1931 machine_mode mode = GET_MODE (x);
kono
parents:
diff changeset
1932 machine_mode inner_mode = GET_MODE (new_reg);
kono
parents:
diff changeset
1933
kono
parents:
diff changeset
1934 if (mode != inner_mode
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1935 && ! (CONST_SCALAR_INT_P (new_reg) && SCALAR_INT_MODE_P (mode)))
111
kono
parents:
diff changeset
1936 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1937 poly_uint64 offset = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1938 if (partial_subreg_p (mode, inner_mode)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1939 && SCALAR_INT_MODE_P (inner_mode))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1940 offset = subreg_lowpart_offset (mode, inner_mode);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1941 if (debug_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1942 new_reg = gen_rtx_raw_SUBREG (mode, new_reg, offset);
111
kono
parents:
diff changeset
1943 else
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1944 new_reg = gen_rtx_SUBREG (mode, new_reg, offset);
111
kono
parents:
diff changeset
1945 }
kono
parents:
diff changeset
1946 *loc = new_reg;
kono
parents:
diff changeset
1947 return true;
kono
parents:
diff changeset
1948 }
kono
parents:
diff changeset
1949
kono
parents:
diff changeset
1950 /* Scan all the operand sub-expressions. */
kono
parents:
diff changeset
1951 fmt = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
1952 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
kono
parents:
diff changeset
1953 {
kono
parents:
diff changeset
1954 if (fmt[i] == 'e')
kono
parents:
diff changeset
1955 {
kono
parents:
diff changeset
1956 if (lra_substitute_pseudo (&XEXP (x, i), old_regno,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1957 new_reg, subreg_p, debug_p))
111
kono
parents:
diff changeset
1958 result = true;
kono
parents:
diff changeset
1959 }
kono
parents:
diff changeset
1960 else if (fmt[i] == 'E')
kono
parents:
diff changeset
1961 {
kono
parents:
diff changeset
1962 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
kono
parents:
diff changeset
1963 if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno,
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1964 new_reg, subreg_p, debug_p))
111
kono
parents:
diff changeset
1965 result = true;
kono
parents:
diff changeset
1966 }
kono
parents:
diff changeset
1967 }
kono
parents:
diff changeset
1968 return result;
kono
parents:
diff changeset
1969 }
kono
parents:
diff changeset
1970
kono
parents:
diff changeset
1971 /* Call lra_substitute_pseudo within an insn. Try to simplify subreg
kono
parents:
diff changeset
1972 of constant if SUBREG_P. This won't update the insn ptr, just the
kono
parents:
diff changeset
1973 contents of the insn. */
kono
parents:
diff changeset
1974 bool
kono
parents:
diff changeset
1975 lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno,
kono
parents:
diff changeset
1976 rtx new_reg, bool subreg_p)
kono
parents:
diff changeset
1977 {
kono
parents:
diff changeset
1978 rtx loc = insn;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1979 return lra_substitute_pseudo (&loc, old_regno, new_reg, subreg_p,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1980 DEBUG_INSN_P (insn));
111
kono
parents:
diff changeset
1981 }
kono
parents:
diff changeset
1982
kono
parents:
diff changeset
1983
kono
parents:
diff changeset
1984
kono
parents:
diff changeset
1985 /* This page contains code dealing with scratches (changing them onto
kono
parents:
diff changeset
1986 pseudos and restoring them from the pseudos).
kono
parents:
diff changeset
1987
kono
parents:
diff changeset
1988 We change scratches into pseudos at the beginning of LRA to
kono
parents:
diff changeset
1989 simplify dealing with them (conflicts, hard register assignments).
kono
parents:
diff changeset
1990
kono
parents:
diff changeset
1991 If the pseudo denoting scratch was spilled it means that we do need
kono
parents:
diff changeset
1992 a hard register for it. Such pseudos are transformed back to
kono
parents:
diff changeset
1993 scratches at the end of LRA. */
kono
parents:
diff changeset
1994
kono
parents:
diff changeset
1995 /* Description of location of a former scratch operand. */
kono
parents:
diff changeset
1996 struct sloc
kono
parents:
diff changeset
1997 {
kono
parents:
diff changeset
1998 rtx_insn *insn; /* Insn where the scratch was. */
kono
parents:
diff changeset
1999 int nop; /* Number of the operand which was a scratch. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2000 int icode; /* Original icode from which scratch was removed. */
111
kono
parents:
diff changeset
2001 };
kono
parents:
diff changeset
2002
kono
parents:
diff changeset
2003 typedef struct sloc *sloc_t;
kono
parents:
diff changeset
2004
kono
parents:
diff changeset
2005 /* Locations of the former scratches. */
kono
parents:
diff changeset
2006 static vec<sloc_t> scratches;
kono
parents:
diff changeset
2007
kono
parents:
diff changeset
2008 /* Bitmap of scratch regnos. */
kono
parents:
diff changeset
2009 static bitmap_head scratch_bitmap;
kono
parents:
diff changeset
2010
kono
parents:
diff changeset
2011 /* Bitmap of scratch operands. */
kono
parents:
diff changeset
2012 static bitmap_head scratch_operand_bitmap;
kono
parents:
diff changeset
2013
kono
parents:
diff changeset
2014 /* Return true if pseudo REGNO is made of SCRATCH. */
kono
parents:
diff changeset
2015 bool
kono
parents:
diff changeset
2016 lra_former_scratch_p (int regno)
kono
parents:
diff changeset
2017 {
kono
parents:
diff changeset
2018 return bitmap_bit_p (&scratch_bitmap, regno);
kono
parents:
diff changeset
2019 }
kono
parents:
diff changeset
2020
kono
parents:
diff changeset
2021 /* Return true if the operand NOP of INSN is a former scratch. */
kono
parents:
diff changeset
2022 bool
kono
parents:
diff changeset
2023 lra_former_scratch_operand_p (rtx_insn *insn, int nop)
kono
parents:
diff changeset
2024 {
kono
parents:
diff changeset
2025 return bitmap_bit_p (&scratch_operand_bitmap,
kono
parents:
diff changeset
2026 INSN_UID (insn) * MAX_RECOG_OPERANDS + nop) != 0;
kono
parents:
diff changeset
2027 }
kono
parents:
diff changeset
2028
kono
parents:
diff changeset
2029 /* Register operand NOP in INSN as a former scratch. It will be
kono
parents:
diff changeset
2030 changed to scratch back, if it is necessary, at the LRA end. */
kono
parents:
diff changeset
2031 void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2032 lra_register_new_scratch_op (rtx_insn *insn, int nop, int icode)
111
kono
parents:
diff changeset
2033 {
kono
parents:
diff changeset
2034 lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
kono
parents:
diff changeset
2035 rtx op = *id->operand_loc[nop];
kono
parents:
diff changeset
2036 sloc_t loc = XNEW (struct sloc);
kono
parents:
diff changeset
2037 lra_assert (REG_P (op));
kono
parents:
diff changeset
2038 loc->insn = insn;
kono
parents:
diff changeset
2039 loc->nop = nop;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2040 loc->icode = icode;
111
kono
parents:
diff changeset
2041 scratches.safe_push (loc);
kono
parents:
diff changeset
2042 bitmap_set_bit (&scratch_bitmap, REGNO (op));
kono
parents:
diff changeset
2043 bitmap_set_bit (&scratch_operand_bitmap,
kono
parents:
diff changeset
2044 INSN_UID (insn) * MAX_RECOG_OPERANDS + nop);
kono
parents:
diff changeset
2045 add_reg_note (insn, REG_UNUSED, op);
kono
parents:
diff changeset
2046 }
kono
parents:
diff changeset
2047
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2048 /* Change INSN's scratches into pseudos and save their location. */
111
kono
parents:
diff changeset
2049 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2050 remove_scratches_1 (rtx_insn *insn)
111
kono
parents:
diff changeset
2051 {
kono
parents:
diff changeset
2052 int i;
kono
parents:
diff changeset
2053 bool insn_changed_p;
kono
parents:
diff changeset
2054 rtx reg;
kono
parents:
diff changeset
2055 lra_insn_recog_data_t id;
kono
parents:
diff changeset
2056 struct lra_static_insn_data *static_id;
kono
parents:
diff changeset
2057
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2058 id = lra_get_insn_recog_data (insn);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2059 static_id = id->insn_static_data;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2060 insn_changed_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2061 for (i = 0; i < static_id->n_operands; i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2062 if (GET_CODE (*id->operand_loc[i]) == SCRATCH
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2063 && GET_MODE (*id->operand_loc[i]) != VOIDmode)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2064 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2065 insn_changed_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2066 *id->operand_loc[i] = reg
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2067 = lra_create_new_reg (static_id->operand[i].mode,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2068 *id->operand_loc[i], ALL_REGS, NULL);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2069 lra_register_new_scratch_op (insn, i, id->icode);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2070 if (lra_dump_file != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2071 fprintf (lra_dump_file,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2072 "Removing SCRATCH in insn #%u (nop %d)\n",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2073 INSN_UID (insn), i);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2074 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2075 if (insn_changed_p)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2076 /* Because we might use DF right after caller-saves sub-pass
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2077 we need to keep DF info up to date. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2078 df_insn_rescan (insn);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2079 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2080
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2081 /* Change scratches into pseudos and save their location. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2082 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2083 remove_scratches (void)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2084 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2085 basic_block bb;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2086 rtx_insn *insn;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2087
111
kono
parents:
diff changeset
2088 scratches.create (get_max_uid ());
kono
parents:
diff changeset
2089 bitmap_initialize (&scratch_bitmap, &reg_obstack);
kono
parents:
diff changeset
2090 bitmap_initialize (&scratch_operand_bitmap, &reg_obstack);
kono
parents:
diff changeset
2091 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
2092 FOR_BB_INSNS (bb, insn)
kono
parents:
diff changeset
2093 if (INSN_P (insn))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2094 remove_scratches_1 (insn);
111
kono
parents:
diff changeset
2095 }
kono
parents:
diff changeset
2096
kono
parents:
diff changeset
2097 /* Changes pseudos created by function remove_scratches onto scratches. */
kono
parents:
diff changeset
2098 static void
kono
parents:
diff changeset
2099 restore_scratches (void)
kono
parents:
diff changeset
2100 {
kono
parents:
diff changeset
2101 int regno;
kono
parents:
diff changeset
2102 unsigned i;
kono
parents:
diff changeset
2103 sloc_t loc;
kono
parents:
diff changeset
2104 rtx_insn *last = NULL;
kono
parents:
diff changeset
2105 lra_insn_recog_data_t id = NULL;
kono
parents:
diff changeset
2106
kono
parents:
diff changeset
2107 for (i = 0; scratches.iterate (i, &loc); i++)
kono
parents:
diff changeset
2108 {
kono
parents:
diff changeset
2109 /* Ignore already deleted insns. */
kono
parents:
diff changeset
2110 if (NOTE_P (loc->insn)
kono
parents:
diff changeset
2111 && NOTE_KIND (loc->insn) == NOTE_INSN_DELETED)
kono
parents:
diff changeset
2112 continue;
kono
parents:
diff changeset
2113 if (last != loc->insn)
kono
parents:
diff changeset
2114 {
kono
parents:
diff changeset
2115 last = loc->insn;
kono
parents:
diff changeset
2116 id = lra_get_insn_recog_data (last);
kono
parents:
diff changeset
2117 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2118 if (loc->icode != id->icode)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2119 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2120 /* The icode doesn't match, which means the insn has been modified
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2121 (e.g. register elimination). The scratch cannot be restored. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2122 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2123 }
111
kono
parents:
diff changeset
2124 if (REG_P (*id->operand_loc[loc->nop])
kono
parents:
diff changeset
2125 && ((regno = REGNO (*id->operand_loc[loc->nop]))
kono
parents:
diff changeset
2126 >= FIRST_PSEUDO_REGISTER)
kono
parents:
diff changeset
2127 && lra_get_regno_hard_regno (regno) < 0)
kono
parents:
diff changeset
2128 {
kono
parents:
diff changeset
2129 /* It should be only case when scratch register with chosen
kono
parents:
diff changeset
2130 constraint 'X' did not get memory or hard register. */
kono
parents:
diff changeset
2131 lra_assert (lra_former_scratch_p (regno));
kono
parents:
diff changeset
2132 *id->operand_loc[loc->nop]
kono
parents:
diff changeset
2133 = gen_rtx_SCRATCH (GET_MODE (*id->operand_loc[loc->nop]));
kono
parents:
diff changeset
2134 lra_update_dup (id, loc->nop);
kono
parents:
diff changeset
2135 if (lra_dump_file != NULL)
kono
parents:
diff changeset
2136 fprintf (lra_dump_file, "Restoring SCRATCH in insn #%u(nop %d)\n",
kono
parents:
diff changeset
2137 INSN_UID (loc->insn), loc->nop);
kono
parents:
diff changeset
2138 }
kono
parents:
diff changeset
2139 }
kono
parents:
diff changeset
2140 for (i = 0; scratches.iterate (i, &loc); i++)
kono
parents:
diff changeset
2141 free (loc);
kono
parents:
diff changeset
2142 scratches.release ();
kono
parents:
diff changeset
2143 bitmap_clear (&scratch_bitmap);
kono
parents:
diff changeset
2144 bitmap_clear (&scratch_operand_bitmap);
kono
parents:
diff changeset
2145 }
kono
parents:
diff changeset
2146
kono
parents:
diff changeset
2147
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 /* Function checks RTL for correctness. If FINAL_P is true, it is
kono
parents:
diff changeset
2150 done at the end of LRA and the check is more rigorous. */
kono
parents:
diff changeset
2151 static void
kono
parents:
diff changeset
2152 check_rtl (bool final_p)
kono
parents:
diff changeset
2153 {
kono
parents:
diff changeset
2154 basic_block bb;
kono
parents:
diff changeset
2155 rtx_insn *insn;
kono
parents:
diff changeset
2156
kono
parents:
diff changeset
2157 lra_assert (! final_p || reload_completed);
kono
parents:
diff changeset
2158 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
2159 FOR_BB_INSNS (bb, insn)
kono
parents:
diff changeset
2160 if (NONDEBUG_INSN_P (insn)
kono
parents:
diff changeset
2161 && GET_CODE (PATTERN (insn)) != USE
kono
parents:
diff changeset
2162 && GET_CODE (PATTERN (insn)) != CLOBBER
kono
parents:
diff changeset
2163 && GET_CODE (PATTERN (insn)) != ASM_INPUT)
kono
parents:
diff changeset
2164 {
kono
parents:
diff changeset
2165 if (final_p)
kono
parents:
diff changeset
2166 {
kono
parents:
diff changeset
2167 extract_constrain_insn (insn);
kono
parents:
diff changeset
2168 continue;
kono
parents:
diff changeset
2169 }
kono
parents:
diff changeset
2170 /* LRA code is based on assumption that all addresses can be
kono
parents:
diff changeset
2171 correctly decomposed. LRA can generate reloads for
kono
parents:
diff changeset
2172 decomposable addresses. The decomposition code checks the
kono
parents:
diff changeset
2173 correctness of the addresses. So we don't need to check
kono
parents:
diff changeset
2174 the addresses here. Don't call insn_invalid_p here, it can
kono
parents:
diff changeset
2175 change the code at this stage. */
kono
parents:
diff changeset
2176 if (recog_memoized (insn) < 0 && asm_noperands (PATTERN (insn)) < 0)
kono
parents:
diff changeset
2177 fatal_insn_not_found (insn);
kono
parents:
diff changeset
2178 }
kono
parents:
diff changeset
2179 }
kono
parents:
diff changeset
2180
kono
parents:
diff changeset
2181 /* Determine if the current function has an exception receiver block
kono
parents:
diff changeset
2182 that reaches the exit block via non-exceptional edges */
kono
parents:
diff changeset
2183 static bool
kono
parents:
diff changeset
2184 has_nonexceptional_receiver (void)
kono
parents:
diff changeset
2185 {
kono
parents:
diff changeset
2186 edge e;
kono
parents:
diff changeset
2187 edge_iterator ei;
kono
parents:
diff changeset
2188 basic_block *tos, *worklist, bb;
kono
parents:
diff changeset
2189
kono
parents:
diff changeset
2190 /* If we're not optimizing, then just err on the safe side. */
kono
parents:
diff changeset
2191 if (!optimize)
kono
parents:
diff changeset
2192 return true;
kono
parents:
diff changeset
2193
kono
parents:
diff changeset
2194 /* First determine which blocks can reach exit via normal paths. */
kono
parents:
diff changeset
2195 tos = worklist = XNEWVEC (basic_block, n_basic_blocks_for_fn (cfun) + 1);
kono
parents:
diff changeset
2196
kono
parents:
diff changeset
2197 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
2198 bb->flags &= ~BB_REACHABLE;
kono
parents:
diff changeset
2199
kono
parents:
diff changeset
2200 /* Place the exit block on our worklist. */
kono
parents:
diff changeset
2201 EXIT_BLOCK_PTR_FOR_FN (cfun)->flags |= BB_REACHABLE;
kono
parents:
diff changeset
2202 *tos++ = EXIT_BLOCK_PTR_FOR_FN (cfun);
kono
parents:
diff changeset
2203
kono
parents:
diff changeset
2204 /* Iterate: find everything reachable from what we've already seen. */
kono
parents:
diff changeset
2205 while (tos != worklist)
kono
parents:
diff changeset
2206 {
kono
parents:
diff changeset
2207 bb = *--tos;
kono
parents:
diff changeset
2208
kono
parents:
diff changeset
2209 FOR_EACH_EDGE (e, ei, bb->preds)
kono
parents:
diff changeset
2210 if (e->flags & EDGE_ABNORMAL)
kono
parents:
diff changeset
2211 {
kono
parents:
diff changeset
2212 free (worklist);
kono
parents:
diff changeset
2213 return true;
kono
parents:
diff changeset
2214 }
kono
parents:
diff changeset
2215 else
kono
parents:
diff changeset
2216 {
kono
parents:
diff changeset
2217 basic_block src = e->src;
kono
parents:
diff changeset
2218
kono
parents:
diff changeset
2219 if (!(src->flags & BB_REACHABLE))
kono
parents:
diff changeset
2220 {
kono
parents:
diff changeset
2221 src->flags |= BB_REACHABLE;
kono
parents:
diff changeset
2222 *tos++ = src;
kono
parents:
diff changeset
2223 }
kono
parents:
diff changeset
2224 }
kono
parents:
diff changeset
2225 }
kono
parents:
diff changeset
2226 free (worklist);
kono
parents:
diff changeset
2227 /* No exceptional block reached exit unexceptionally. */
kono
parents:
diff changeset
2228 return false;
kono
parents:
diff changeset
2229 }
kono
parents:
diff changeset
2230
kono
parents:
diff changeset
2231
kono
parents:
diff changeset
2232 /* Process recursively X of INSN and add REG_INC notes if necessary. */
kono
parents:
diff changeset
2233 static void
kono
parents:
diff changeset
2234 add_auto_inc_notes (rtx_insn *insn, rtx x)
kono
parents:
diff changeset
2235 {
kono
parents:
diff changeset
2236 enum rtx_code code = GET_CODE (x);
kono
parents:
diff changeset
2237 const char *fmt;
kono
parents:
diff changeset
2238 int i, j;
kono
parents:
diff changeset
2239
kono
parents:
diff changeset
2240 if (code == MEM && auto_inc_p (XEXP (x, 0)))
kono
parents:
diff changeset
2241 {
kono
parents:
diff changeset
2242 add_reg_note (insn, REG_INC, XEXP (XEXP (x, 0), 0));
kono
parents:
diff changeset
2243 return;
kono
parents:
diff changeset
2244 }
kono
parents:
diff changeset
2245
kono
parents:
diff changeset
2246 /* Scan all X sub-expressions. */
kono
parents:
diff changeset
2247 fmt = GET_RTX_FORMAT (code);
kono
parents:
diff changeset
2248 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
kono
parents:
diff changeset
2249 {
kono
parents:
diff changeset
2250 if (fmt[i] == 'e')
kono
parents:
diff changeset
2251 add_auto_inc_notes (insn, XEXP (x, i));
kono
parents:
diff changeset
2252 else if (fmt[i] == 'E')
kono
parents:
diff changeset
2253 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
kono
parents:
diff changeset
2254 add_auto_inc_notes (insn, XVECEXP (x, i, j));
kono
parents:
diff changeset
2255 }
kono
parents:
diff changeset
2256 }
kono
parents:
diff changeset
2257
kono
parents:
diff changeset
2258
kono
parents:
diff changeset
2259 /* Remove all REG_DEAD and REG_UNUSED notes and regenerate REG_INC.
kono
parents:
diff changeset
2260 We change pseudos by hard registers without notification of DF and
kono
parents:
diff changeset
2261 that can make the notes obsolete. DF-infrastructure does not deal
kono
parents:
diff changeset
2262 with REG_INC notes -- so we should regenerate them here. */
kono
parents:
diff changeset
2263 static void
kono
parents:
diff changeset
2264 update_inc_notes (void)
kono
parents:
diff changeset
2265 {
kono
parents:
diff changeset
2266 rtx *pnote;
kono
parents:
diff changeset
2267 basic_block bb;
kono
parents:
diff changeset
2268 rtx_insn *insn;
kono
parents:
diff changeset
2269
kono
parents:
diff changeset
2270 FOR_EACH_BB_FN (bb, cfun)
kono
parents:
diff changeset
2271 FOR_BB_INSNS (bb, insn)
kono
parents:
diff changeset
2272 if (NONDEBUG_INSN_P (insn))
kono
parents:
diff changeset
2273 {
kono
parents:
diff changeset
2274 pnote = &REG_NOTES (insn);
kono
parents:
diff changeset
2275 while (*pnote != 0)
kono
parents:
diff changeset
2276 {
kono
parents:
diff changeset
2277 if (REG_NOTE_KIND (*pnote) == REG_DEAD
kono
parents:
diff changeset
2278 || REG_NOTE_KIND (*pnote) == REG_UNUSED
kono
parents:
diff changeset
2279 || REG_NOTE_KIND (*pnote) == REG_INC)
kono
parents:
diff changeset
2280 *pnote = XEXP (*pnote, 1);
kono
parents:
diff changeset
2281 else
kono
parents:
diff changeset
2282 pnote = &XEXP (*pnote, 1);
kono
parents:
diff changeset
2283 }
kono
parents:
diff changeset
2284
kono
parents:
diff changeset
2285 if (AUTO_INC_DEC)
kono
parents:
diff changeset
2286 add_auto_inc_notes (insn, PATTERN (insn));
kono
parents:
diff changeset
2287 }
kono
parents:
diff changeset
2288 }
kono
parents:
diff changeset
2289
kono
parents:
diff changeset
2290 /* Set to 1 while in lra. */
kono
parents:
diff changeset
2291 int lra_in_progress;
kono
parents:
diff changeset
2292
kono
parents:
diff changeset
2293 /* Start of pseudo regnos before the LRA. */
kono
parents:
diff changeset
2294 int lra_new_regno_start;
kono
parents:
diff changeset
2295
kono
parents:
diff changeset
2296 /* Start of reload pseudo regnos before the new spill pass. */
kono
parents:
diff changeset
2297 int lra_constraint_new_regno_start;
kono
parents:
diff changeset
2298
kono
parents:
diff changeset
2299 /* Avoid spilling pseudos with regno more than the following value if
kono
parents:
diff changeset
2300 it is possible. */
kono
parents:
diff changeset
2301 int lra_bad_spill_regno_start;
kono
parents:
diff changeset
2302
kono
parents:
diff changeset
2303 /* Inheritance pseudo regnos before the new spill pass. */
kono
parents:
diff changeset
2304 bitmap_head lra_inheritance_pseudos;
kono
parents:
diff changeset
2305
kono
parents:
diff changeset
2306 /* Split regnos before the new spill pass. */
kono
parents:
diff changeset
2307 bitmap_head lra_split_regs;
kono
parents:
diff changeset
2308
kono
parents:
diff changeset
2309 /* Reload pseudo regnos before the new assignment pass which still can
kono
parents:
diff changeset
2310 be spilled after the assignment pass as memory is also accepted in
kono
parents:
diff changeset
2311 insns for the reload pseudos. */
kono
parents:
diff changeset
2312 bitmap_head lra_optional_reload_pseudos;
kono
parents:
diff changeset
2313
kono
parents:
diff changeset
2314 /* Pseudo regnos used for subreg reloads before the new assignment
kono
parents:
diff changeset
2315 pass. Such pseudos still can be spilled after the assignment
kono
parents:
diff changeset
2316 pass. */
kono
parents:
diff changeset
2317 bitmap_head lra_subreg_reload_pseudos;
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 /* File used for output of LRA debug information. */
kono
parents:
diff changeset
2320 FILE *lra_dump_file;
kono
parents:
diff changeset
2321
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2322 /* True if we found an asm error. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2323 bool lra_asm_error_p;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2324
111
kono
parents:
diff changeset
2325 /* True if we should try spill into registers of different classes
kono
parents:
diff changeset
2326 instead of memory. */
kono
parents:
diff changeset
2327 bool lra_reg_spill_p;
kono
parents:
diff changeset
2328
kono
parents:
diff changeset
2329 /* Set up value LRA_REG_SPILL_P. */
kono
parents:
diff changeset
2330 static void
kono
parents:
diff changeset
2331 setup_reg_spill_flag (void)
kono
parents:
diff changeset
2332 {
kono
parents:
diff changeset
2333 int cl, mode;
kono
parents:
diff changeset
2334
kono
parents:
diff changeset
2335 if (targetm.spill_class != NULL)
kono
parents:
diff changeset
2336 for (cl = 0; cl < (int) LIM_REG_CLASSES; cl++)
kono
parents:
diff changeset
2337 for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
kono
parents:
diff changeset
2338 if (targetm.spill_class ((enum reg_class) cl,
kono
parents:
diff changeset
2339 (machine_mode) mode) != NO_REGS)
kono
parents:
diff changeset
2340 {
kono
parents:
diff changeset
2341 lra_reg_spill_p = true;
kono
parents:
diff changeset
2342 return;
kono
parents:
diff changeset
2343 }
kono
parents:
diff changeset
2344 lra_reg_spill_p = false;
kono
parents:
diff changeset
2345 }
kono
parents:
diff changeset
2346
kono
parents:
diff changeset
2347 /* True if the current function is too big to use regular algorithms
kono
parents:
diff changeset
2348 in LRA. In other words, we should use simpler and faster algorithms
kono
parents:
diff changeset
2349 in LRA. It also means we should not worry about generation code
kono
parents:
diff changeset
2350 for caller saves. The value is set up in IRA. */
kono
parents:
diff changeset
2351 bool lra_simple_p;
kono
parents:
diff changeset
2352
kono
parents:
diff changeset
2353 /* Major LRA entry function. F is a file should be used to dump LRA
kono
parents:
diff changeset
2354 debug info. */
kono
parents:
diff changeset
2355 void
kono
parents:
diff changeset
2356 lra (FILE *f)
kono
parents:
diff changeset
2357 {
kono
parents:
diff changeset
2358 int i;
kono
parents:
diff changeset
2359 bool live_p, inserted_p;
kono
parents:
diff changeset
2360
kono
parents:
diff changeset
2361 lra_dump_file = f;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2362 lra_asm_error_p = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2363
111
kono
parents:
diff changeset
2364 timevar_push (TV_LRA);
kono
parents:
diff changeset
2365
kono
parents:
diff changeset
2366 /* Make sure that the last insn is a note. Some subsequent passes
kono
parents:
diff changeset
2367 need it. */
kono
parents:
diff changeset
2368 emit_note (NOTE_INSN_DELETED);
kono
parents:
diff changeset
2369
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2370 lra_no_alloc_regs = ira_no_alloc_regs;
111
kono
parents:
diff changeset
2371
kono
parents:
diff changeset
2372 init_reg_info ();
kono
parents:
diff changeset
2373 expand_reg_info ();
kono
parents:
diff changeset
2374
kono
parents:
diff changeset
2375 init_insn_recog_data ();
kono
parents:
diff changeset
2376
kono
parents:
diff changeset
2377 /* Some quick check on RTL generated by previous passes. */
kono
parents:
diff changeset
2378 if (flag_checking)
kono
parents:
diff changeset
2379 check_rtl (false);
kono
parents:
diff changeset
2380
kono
parents:
diff changeset
2381 lra_in_progress = 1;
kono
parents:
diff changeset
2382
kono
parents:
diff changeset
2383 lra_live_range_iter = lra_coalesce_iter = lra_constraint_iter = 0;
kono
parents:
diff changeset
2384 lra_assignment_iter = lra_assignment_iter_after_spill = 0;
kono
parents:
diff changeset
2385 lra_inheritance_iter = lra_undo_inheritance_iter = 0;
kono
parents:
diff changeset
2386 lra_rematerialization_iter = 0;
kono
parents:
diff changeset
2387
kono
parents:
diff changeset
2388 setup_reg_spill_flag ();
kono
parents:
diff changeset
2389
kono
parents:
diff changeset
2390 /* Function remove_scratches can creates new pseudos for clobbers --
kono
parents:
diff changeset
2391 so set up lra_constraint_new_regno_start before its call to
kono
parents:
diff changeset
2392 permit changing reg classes for pseudos created by this
kono
parents:
diff changeset
2393 simplification. */
kono
parents:
diff changeset
2394 lra_constraint_new_regno_start = lra_new_regno_start = max_reg_num ();
kono
parents:
diff changeset
2395 lra_bad_spill_regno_start = INT_MAX;
kono
parents:
diff changeset
2396 remove_scratches ();
kono
parents:
diff changeset
2397
kono
parents:
diff changeset
2398 /* A function that has a non-local label that can reach the exit
kono
parents:
diff changeset
2399 block via non-exceptional paths must save all call-saved
kono
parents:
diff changeset
2400 registers. */
kono
parents:
diff changeset
2401 if (cfun->has_nonlocal_label && has_nonexceptional_receiver ())
kono
parents:
diff changeset
2402 crtl->saves_all_registers = 1;
kono
parents:
diff changeset
2403
kono
parents:
diff changeset
2404 if (crtl->saves_all_registers)
kono
parents:
diff changeset
2405 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2406 if (!crtl->abi->clobbers_full_reg_p (i)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2407 && !fixed_regs[i]
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2408 && !LOCAL_REGNO (i))
111
kono
parents:
diff changeset
2409 df_set_regs_ever_live (i, true);
kono
parents:
diff changeset
2410
kono
parents:
diff changeset
2411 /* We don't DF from now and avoid its using because it is to
kono
parents:
diff changeset
2412 expensive when a lot of RTL changes are made. */
kono
parents:
diff changeset
2413 df_set_flags (DF_NO_INSN_RESCAN);
kono
parents:
diff changeset
2414 lra_constraint_insn_stack.create (get_max_uid ());
kono
parents:
diff changeset
2415 lra_constraint_insn_stack_bitmap = sbitmap_alloc (get_max_uid ());
kono
parents:
diff changeset
2416 bitmap_clear (lra_constraint_insn_stack_bitmap);
kono
parents:
diff changeset
2417 lra_live_ranges_init ();
kono
parents:
diff changeset
2418 lra_constraints_init ();
kono
parents:
diff changeset
2419 lra_curr_reload_num = 0;
kono
parents:
diff changeset
2420 push_insns (get_last_insn (), NULL);
kono
parents:
diff changeset
2421 /* It is needed for the 1st coalescing. */
kono
parents:
diff changeset
2422 bitmap_initialize (&lra_inheritance_pseudos, &reg_obstack);
kono
parents:
diff changeset
2423 bitmap_initialize (&lra_split_regs, &reg_obstack);
kono
parents:
diff changeset
2424 bitmap_initialize (&lra_optional_reload_pseudos, &reg_obstack);
kono
parents:
diff changeset
2425 bitmap_initialize (&lra_subreg_reload_pseudos, &reg_obstack);
kono
parents:
diff changeset
2426 live_p = false;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2427 if (maybe_ne (get_frame_size (), 0) && crtl->stack_alignment_needed)
111
kono
parents:
diff changeset
2428 /* If we have a stack frame, we must align it now. The stack size
kono
parents:
diff changeset
2429 may be a part of the offset computation for register
kono
parents:
diff changeset
2430 elimination. */
kono
parents:
diff changeset
2431 assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed);
kono
parents:
diff changeset
2432 lra_init_equiv ();
kono
parents:
diff changeset
2433 for (;;)
kono
parents:
diff changeset
2434 {
kono
parents:
diff changeset
2435 for (;;)
kono
parents:
diff changeset
2436 {
kono
parents:
diff changeset
2437 bool reloads_p = lra_constraints (lra_constraint_iter == 0);
kono
parents:
diff changeset
2438 /* Constraint transformations may result in that eliminable
kono
parents:
diff changeset
2439 hard regs become uneliminable and pseudos which use them
kono
parents:
diff changeset
2440 should be spilled. It is better to do it before pseudo
kono
parents:
diff changeset
2441 assignments.
kono
parents:
diff changeset
2442
kono
parents:
diff changeset
2443 For example, rs6000 can make
kono
parents:
diff changeset
2444 RS6000_PIC_OFFSET_TABLE_REGNUM uneliminable if we started
kono
parents:
diff changeset
2445 to use a constant pool. */
kono
parents:
diff changeset
2446 lra_eliminate (false, false);
kono
parents:
diff changeset
2447 /* We should try to assign hard registers to scratches even
kono
parents:
diff changeset
2448 if there were no RTL transformations in lra_constraints.
kono
parents:
diff changeset
2449 Also we should check IRA assignments on the first
kono
parents:
diff changeset
2450 iteration as they can be wrong because of early clobbers
kono
parents:
diff changeset
2451 operands which are ignored in IRA. */
kono
parents:
diff changeset
2452 if (! reloads_p && lra_constraint_iter > 1)
kono
parents:
diff changeset
2453 {
kono
parents:
diff changeset
2454 /* Stack is not empty here only when there are changes
kono
parents:
diff changeset
2455 during the elimination sub-pass. */
kono
parents:
diff changeset
2456 if (bitmap_empty_p (lra_constraint_insn_stack_bitmap))
kono
parents:
diff changeset
2457 break;
kono
parents:
diff changeset
2458 else
kono
parents:
diff changeset
2459 /* If there are no reloads but changing due
kono
parents:
diff changeset
2460 elimination, restart the constraint sub-pass
kono
parents:
diff changeset
2461 first. */
kono
parents:
diff changeset
2462 continue;
kono
parents:
diff changeset
2463 }
kono
parents:
diff changeset
2464 /* Do inheritance only for regular algorithms. */
kono
parents:
diff changeset
2465 if (! lra_simple_p)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2466 lra_inheritance ();
111
kono
parents:
diff changeset
2467 if (live_p)
kono
parents:
diff changeset
2468 lra_clear_live_ranges ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2469 bool fails_p;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2470 do
111
kono
parents:
diff changeset
2471 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2472 /* We need live ranges for lra_assign -- so build them.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2473 But don't remove dead insns or change global live
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2474 info as we can undo inheritance transformations after
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2475 inheritance pseudo assigning. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2476 lra_create_live_ranges (true, !lra_simple_p);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2477 live_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2478 /* If we don't spill non-reload and non-inheritance
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2479 pseudos, there is no sense to run memory-memory move
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2480 coalescing. If inheritance pseudos were spilled, the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2481 memory-memory moves involving them will be removed by
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2482 pass undoing inheritance. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2483 if (lra_simple_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2484 lra_assign (fails_p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2485 else
111
kono
parents:
diff changeset
2486 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2487 bool spill_p = !lra_assign (fails_p);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2488
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2489 if (lra_undo_inheritance ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2490 live_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2491 if (spill_p && ! fails_p)
111
kono
parents:
diff changeset
2492 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2493 if (! live_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2494 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2495 lra_create_live_ranges (true, true);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2496 live_p = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2497 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2498 if (lra_coalesce ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2499 live_p = false;
111
kono
parents:
diff changeset
2500 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2501 if (! live_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2502 lra_clear_live_ranges ();
111
kono
parents:
diff changeset
2503 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2504 if (fails_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2505 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2506 /* It is a very rare case. It is the last hope to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2507 split a hard regno live range for a reload
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2508 pseudo. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2509 if (live_p)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2510 lra_clear_live_ranges ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2511 live_p = false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2512 if (! lra_split_hard_reg_for ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2513 break;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2514 }
111
kono
parents:
diff changeset
2515 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2516 while (fails_p);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2517 if (! live_p) {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2518 /* We need the correct reg notes for work of constraint sub-pass. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2519 lra_create_live_ranges (true, true);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2520 live_p = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2521 }
111
kono
parents:
diff changeset
2522 }
kono
parents:
diff changeset
2523 /* Don't clear optional reloads bitmap until all constraints are
kono
parents:
diff changeset
2524 satisfied as we need to differ them from regular reloads. */
kono
parents:
diff changeset
2525 bitmap_clear (&lra_optional_reload_pseudos);
kono
parents:
diff changeset
2526 bitmap_clear (&lra_subreg_reload_pseudos);
kono
parents:
diff changeset
2527 bitmap_clear (&lra_inheritance_pseudos);
kono
parents:
diff changeset
2528 bitmap_clear (&lra_split_regs);
kono
parents:
diff changeset
2529 if (! live_p)
kono
parents:
diff changeset
2530 {
kono
parents:
diff changeset
2531 /* We need full live info for spilling pseudos into
kono
parents:
diff changeset
2532 registers instead of memory. */
kono
parents:
diff changeset
2533 lra_create_live_ranges (lra_reg_spill_p, true);
kono
parents:
diff changeset
2534 live_p = true;
kono
parents:
diff changeset
2535 }
kono
parents:
diff changeset
2536 /* We should check necessity for spilling here as the above live
kono
parents:
diff changeset
2537 range pass can remove spilled pseudos. */
kono
parents:
diff changeset
2538 if (! lra_need_for_spills_p ())
kono
parents:
diff changeset
2539 break;
kono
parents:
diff changeset
2540 /* Now we know what pseudos should be spilled. Try to
kono
parents:
diff changeset
2541 rematerialize them first. */
kono
parents:
diff changeset
2542 if (lra_remat ())
kono
parents:
diff changeset
2543 {
kono
parents:
diff changeset
2544 /* We need full live info -- see the comment above. */
kono
parents:
diff changeset
2545 lra_create_live_ranges (lra_reg_spill_p, true);
kono
parents:
diff changeset
2546 live_p = true;
kono
parents:
diff changeset
2547 if (! lra_need_for_spills_p ())
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2548 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2549 if (lra_need_for_scratch_reg_p ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2550 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2551 break;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2552 }
111
kono
parents:
diff changeset
2553 }
kono
parents:
diff changeset
2554 lra_spill ();
kono
parents:
diff changeset
2555 /* Assignment of stack slots changes elimination offsets for
kono
parents:
diff changeset
2556 some eliminations. So update the offsets here. */
kono
parents:
diff changeset
2557 lra_eliminate (false, false);
kono
parents:
diff changeset
2558 lra_constraint_new_regno_start = max_reg_num ();
kono
parents:
diff changeset
2559 if (lra_bad_spill_regno_start == INT_MAX
kono
parents:
diff changeset
2560 && lra_inheritance_iter > LRA_MAX_INHERITANCE_PASSES
kono
parents:
diff changeset
2561 && lra_rematerialization_iter > LRA_MAX_REMATERIALIZATION_PASSES)
kono
parents:
diff changeset
2562 /* After switching off inheritance and rematerialization
kono
parents:
diff changeset
2563 passes, avoid spilling reload pseudos will be created to
kono
parents:
diff changeset
2564 prevent LRA cycling in some complicated cases. */
kono
parents:
diff changeset
2565 lra_bad_spill_regno_start = lra_constraint_new_regno_start;
kono
parents:
diff changeset
2566 lra_assignment_iter_after_spill = 0;
kono
parents:
diff changeset
2567 }
kono
parents:
diff changeset
2568 restore_scratches ();
kono
parents:
diff changeset
2569 lra_eliminate (true, false);
kono
parents:
diff changeset
2570 lra_final_code_change ();
kono
parents:
diff changeset
2571 lra_in_progress = 0;
kono
parents:
diff changeset
2572 if (live_p)
kono
parents:
diff changeset
2573 lra_clear_live_ranges ();
kono
parents:
diff changeset
2574 lra_live_ranges_finish ();
kono
parents:
diff changeset
2575 lra_constraints_finish ();
kono
parents:
diff changeset
2576 finish_reg_info ();
kono
parents:
diff changeset
2577 sbitmap_free (lra_constraint_insn_stack_bitmap);
kono
parents:
diff changeset
2578 lra_constraint_insn_stack.release ();
kono
parents:
diff changeset
2579 finish_insn_recog_data ();
kono
parents:
diff changeset
2580 regstat_free_n_sets_and_refs ();
kono
parents:
diff changeset
2581 regstat_free_ri ();
kono
parents:
diff changeset
2582 reload_completed = 1;
kono
parents:
diff changeset
2583 update_inc_notes ();
kono
parents:
diff changeset
2584
kono
parents:
diff changeset
2585 inserted_p = fixup_abnormal_edges ();
kono
parents:
diff changeset
2586
kono
parents:
diff changeset
2587 /* We've possibly turned single trapping insn into multiple ones. */
kono
parents:
diff changeset
2588 if (cfun->can_throw_non_call_exceptions)
kono
parents:
diff changeset
2589 {
kono
parents:
diff changeset
2590 auto_sbitmap blocks (last_basic_block_for_fn (cfun));
kono
parents:
diff changeset
2591 bitmap_ones (blocks);
kono
parents:
diff changeset
2592 find_many_sub_basic_blocks (blocks);
kono
parents:
diff changeset
2593 }
kono
parents:
diff changeset
2594
kono
parents:
diff changeset
2595 if (inserted_p)
kono
parents:
diff changeset
2596 commit_edge_insertions ();
kono
parents:
diff changeset
2597
kono
parents:
diff changeset
2598 /* Replacing pseudos with their memory equivalents might have
kono
parents:
diff changeset
2599 created shared rtx. Subsequent passes would get confused
kono
parents:
diff changeset
2600 by this, so unshare everything here. */
kono
parents:
diff changeset
2601 unshare_all_rtl_again (get_insns ());
kono
parents:
diff changeset
2602
kono
parents:
diff changeset
2603 if (flag_checking)
kono
parents:
diff changeset
2604 check_rtl (true);
kono
parents:
diff changeset
2605
kono
parents:
diff changeset
2606 timevar_pop (TV_LRA);
kono
parents:
diff changeset
2607 }
kono
parents:
diff changeset
2608
kono
parents:
diff changeset
2609 /* Called once per compiler to initialize LRA data once. */
kono
parents:
diff changeset
2610 void
kono
parents:
diff changeset
2611 lra_init_once (void)
kono
parents:
diff changeset
2612 {
kono
parents:
diff changeset
2613 init_insn_code_data_once ();
kono
parents:
diff changeset
2614 }
kono
parents:
diff changeset
2615
kono
parents:
diff changeset
2616 /* Called once per compiler to finish LRA data which are initialize
kono
parents:
diff changeset
2617 once. */
kono
parents:
diff changeset
2618 void
kono
parents:
diff changeset
2619 lra_finish_once (void)
kono
parents:
diff changeset
2620 {
kono
parents:
diff changeset
2621 finish_insn_code_data_once ();
kono
parents:
diff changeset
2622 }