File: | build/gcc/combine.cc |
Warning: | line 4505, column 9 Branch condition evaluates to a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Optimize by combining instructions for GNU compiler. | ||||||
2 | Copyright (C) 1987-2023 Free Software Foundation, Inc. | ||||||
3 | |||||||
4 | This file is part of GCC. | ||||||
5 | |||||||
6 | GCC is free software; you can redistribute it and/or modify it under | ||||||
7 | the terms of the GNU General Public License as published by the Free | ||||||
8 | Software Foundation; either version 3, or (at your option) any later | ||||||
9 | version. | ||||||
10 | |||||||
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | ||||||
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||||||
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||||||
14 | for more details. | ||||||
15 | |||||||
16 | You should have received a copy of the GNU General Public License | ||||||
17 | along with GCC; see the file COPYING3. If not see | ||||||
18 | <http://www.gnu.org/licenses/>. */ | ||||||
19 | |||||||
20 | /* This module is essentially the "combiner" phase of the U. of Arizona | ||||||
21 | Portable Optimizer, but redone to work on our list-structured | ||||||
22 | representation for RTL instead of their string representation. | ||||||
23 | |||||||
24 | The LOG_LINKS of each insn identify the most recent assignment | ||||||
25 | to each REG used in the insn. It is a list of previous insns, | ||||||
26 | each of which contains a SET for a REG that is used in this insn | ||||||
27 | and not used or set in between. LOG_LINKs never cross basic blocks. | ||||||
28 | They were set up by the preceding pass (lifetime analysis). | ||||||
29 | |||||||
30 | We try to combine each pair of insns joined by a logical link. | ||||||
31 | We also try to combine triplets of insns A, B and C when C has | ||||||
32 | a link back to B and B has a link back to A. Likewise for a | ||||||
33 | small number of quadruplets of insns A, B, C and D for which | ||||||
34 | there's high likelihood of success. | ||||||
35 | |||||||
36 | We check (with modified_between_p) to avoid combining in such a way | ||||||
37 | as to move a computation to a place where its value would be different. | ||||||
38 | |||||||
39 | Combination is done by mathematically substituting the previous | ||||||
40 | insn(s) values for the regs they set into the expressions in | ||||||
41 | the later insns that refer to these regs. If the result is a valid insn | ||||||
42 | for our target machine, according to the machine description, | ||||||
43 | we install it, delete the earlier insns, and update the data flow | ||||||
44 | information (LOG_LINKS and REG_NOTES) for what we did. | ||||||
45 | |||||||
46 | There are a few exceptions where the dataflow information isn't | ||||||
47 | completely updated (however this is only a local issue since it is | ||||||
48 | regenerated before the next pass that uses it): | ||||||
49 | |||||||
50 | - reg_live_length is not updated | ||||||
51 | - reg_n_refs is not adjusted in the rare case when a register is | ||||||
52 | no longer required in a computation | ||||||
53 | - there are extremely rare cases (see distribute_notes) when a | ||||||
54 | REG_DEAD note is lost | ||||||
55 | - a LOG_LINKS entry that refers to an insn with multiple SETs may be | ||||||
56 | removed because there is no way to know which register it was | ||||||
57 | linking | ||||||
58 | |||||||
59 | To simplify substitution, we combine only when the earlier insn(s) | ||||||
60 | consist of only a single assignment. To simplify updating afterward, | ||||||
61 | we never combine when a subroutine call appears in the middle. */ | ||||||
62 | |||||||
63 | #include "config.h" | ||||||
64 | #include "system.h" | ||||||
65 | #include "coretypes.h" | ||||||
66 | #include "backend.h" | ||||||
67 | #include "target.h" | ||||||
68 | #include "rtl.h" | ||||||
69 | #include "tree.h" | ||||||
70 | #include "cfghooks.h" | ||||||
71 | #include "predict.h" | ||||||
72 | #include "df.h" | ||||||
73 | #include "memmodel.h" | ||||||
74 | #include "tm_p.h" | ||||||
75 | #include "optabs.h" | ||||||
76 | #include "regs.h" | ||||||
77 | #include "emit-rtl.h" | ||||||
78 | #include "recog.h" | ||||||
79 | #include "cgraph.h" | ||||||
80 | #include "stor-layout.h" | ||||||
81 | #include "cfgrtl.h" | ||||||
82 | #include "cfgcleanup.h" | ||||||
83 | /* Include expr.h after insn-config.h so we get HAVE_conditional_move. */ | ||||||
84 | #include "explow.h" | ||||||
85 | #include "insn-attr.h" | ||||||
86 | #include "rtlhooks-def.h" | ||||||
87 | #include "expr.h" | ||||||
88 | #include "tree-pass.h" | ||||||
89 | #include "valtrack.h" | ||||||
90 | #include "rtl-iter.h" | ||||||
91 | #include "print-rtl.h" | ||||||
92 | #include "function-abi.h" | ||||||
93 | #include "rtlanal.h" | ||||||
94 | |||||||
95 | /* Number of attempts to combine instructions in this function. */ | ||||||
96 | |||||||
97 | static int combine_attempts; | ||||||
98 | |||||||
99 | /* Number of attempts that got as far as substitution in this function. */ | ||||||
100 | |||||||
101 | static int combine_merges; | ||||||
102 | |||||||
103 | /* Number of instructions combined with added SETs in this function. */ | ||||||
104 | |||||||
105 | static int combine_extras; | ||||||
106 | |||||||
107 | /* Number of instructions combined in this function. */ | ||||||
108 | |||||||
109 | static int combine_successes; | ||||||
110 | |||||||
111 | /* Totals over entire compilation. */ | ||||||
112 | |||||||
113 | static int total_attempts, total_merges, total_extras, total_successes; | ||||||
114 | |||||||
115 | /* combine_instructions may try to replace the right hand side of the | ||||||
116 | second instruction with the value of an associated REG_EQUAL note | ||||||
117 | before throwing it at try_combine. That is problematic when there | ||||||
118 | is a REG_DEAD note for a register used in the old right hand side | ||||||
119 | and can cause distribute_notes to do wrong things. This is the | ||||||
120 | second instruction if it has been so modified, null otherwise. */ | ||||||
121 | |||||||
122 | static rtx_insn *i2mod; | ||||||
123 | |||||||
124 | /* When I2MOD is nonnull, this is a copy of the old right hand side. */ | ||||||
125 | |||||||
126 | static rtx i2mod_old_rhs; | ||||||
127 | |||||||
128 | /* When I2MOD is nonnull, this is a copy of the new right hand side. */ | ||||||
129 | |||||||
130 | static rtx i2mod_new_rhs; | ||||||
131 | |||||||
132 | struct reg_stat_type { | ||||||
133 | /* Record last point of death of (hard or pseudo) register n. */ | ||||||
134 | rtx_insn *last_death; | ||||||
135 | |||||||
136 | /* Record last point of modification of (hard or pseudo) register n. */ | ||||||
137 | rtx_insn *last_set; | ||||||
138 | |||||||
139 | /* The next group of fields allows the recording of the last value assigned | ||||||
140 | to (hard or pseudo) register n. We use this information to see if an | ||||||
141 | operation being processed is redundant given a prior operation performed | ||||||
142 | on the register. For example, an `and' with a constant is redundant if | ||||||
143 | all the zero bits are already known to be turned off. | ||||||
144 | |||||||
145 | We use an approach similar to that used by cse, but change it in the | ||||||
146 | following ways: | ||||||
147 | |||||||
148 | (1) We do not want to reinitialize at each label. | ||||||
149 | (2) It is useful, but not critical, to know the actual value assigned | ||||||
150 | to a register. Often just its form is helpful. | ||||||
151 | |||||||
152 | Therefore, we maintain the following fields: | ||||||
153 | |||||||
154 | last_set_value the last value assigned | ||||||
155 | last_set_label records the value of label_tick when the | ||||||
156 | register was assigned | ||||||
157 | last_set_table_tick records the value of label_tick when a | ||||||
158 | value using the register is assigned | ||||||
159 | last_set_invalid set to nonzero when it is not valid | ||||||
160 | to use the value of this register in some | ||||||
161 | register's value | ||||||
162 | |||||||
163 | To understand the usage of these tables, it is important to understand | ||||||
164 | the distinction between the value in last_set_value being valid and | ||||||
165 | the register being validly contained in some other expression in the | ||||||
166 | table. | ||||||
167 | |||||||
168 | (The next two parameters are out of date). | ||||||
169 | |||||||
170 | reg_stat[i].last_set_value is valid if it is nonzero, and either | ||||||
171 | reg_n_sets[i] is 1 or reg_stat[i].last_set_label == label_tick. | ||||||
172 | |||||||
173 | Register I may validly appear in any expression returned for the value | ||||||
174 | of another register if reg_n_sets[i] is 1. It may also appear in the | ||||||
175 | value for register J if reg_stat[j].last_set_invalid is zero, or | ||||||
176 | reg_stat[i].last_set_label < reg_stat[j].last_set_label. | ||||||
177 | |||||||
178 | If an expression is found in the table containing a register which may | ||||||
179 | not validly appear in an expression, the register is replaced by | ||||||
180 | something that won't match, (clobber (const_int 0)). */ | ||||||
181 | |||||||
182 | /* Record last value assigned to (hard or pseudo) register n. */ | ||||||
183 | |||||||
184 | rtx last_set_value; | ||||||
185 | |||||||
186 | /* Record the value of label_tick when an expression involving register n | ||||||
187 | is placed in last_set_value. */ | ||||||
188 | |||||||
189 | int last_set_table_tick; | ||||||
190 | |||||||
191 | /* Record the value of label_tick when the value for register n is placed in | ||||||
192 | last_set_value. */ | ||||||
193 | |||||||
194 | int last_set_label; | ||||||
195 | |||||||
196 | /* These fields are maintained in parallel with last_set_value and are | ||||||
197 | used to store the mode in which the register was last set, the bits | ||||||
198 | that were known to be zero when it was last set, and the number of | ||||||
199 | sign bits copies it was known to have when it was last set. */ | ||||||
200 | |||||||
201 | unsigned HOST_WIDE_INTlong last_set_nonzero_bits; | ||||||
202 | char last_set_sign_bit_copies; | ||||||
203 | ENUM_BITFIELD(machine_mode)enum machine_mode last_set_mode : 8; | ||||||
204 | |||||||
205 | /* Set nonzero if references to register n in expressions should not be | ||||||
206 | used. last_set_invalid is set nonzero when this register is being | ||||||
207 | assigned to and last_set_table_tick == label_tick. */ | ||||||
208 | |||||||
209 | char last_set_invalid; | ||||||
210 | |||||||
211 | /* Some registers that are set more than once and used in more than one | ||||||
212 | basic block are nevertheless always set in similar ways. For example, | ||||||
213 | a QImode register may be loaded from memory in two places on a machine | ||||||
214 | where byte loads zero extend. | ||||||
215 | |||||||
216 | We record in the following fields if a register has some leading bits | ||||||
217 | that are always equal to the sign bit, and what we know about the | ||||||
218 | nonzero bits of a register, specifically which bits are known to be | ||||||
219 | zero. | ||||||
220 | |||||||
221 | If an entry is zero, it means that we don't know anything special. */ | ||||||
222 | |||||||
223 | unsigned char sign_bit_copies; | ||||||
224 | |||||||
225 | unsigned HOST_WIDE_INTlong nonzero_bits; | ||||||
226 | |||||||
227 | /* Record the value of the label_tick when the last truncation | ||||||
228 | happened. The field truncated_to_mode is only valid if | ||||||
229 | truncation_label == label_tick. */ | ||||||
230 | |||||||
231 | int truncation_label; | ||||||
232 | |||||||
233 | /* Record the last truncation seen for this register. If truncation | ||||||
234 | is not a nop to this mode we might be able to save an explicit | ||||||
235 | truncation if we know that value already contains a truncated | ||||||
236 | value. */ | ||||||
237 | |||||||
238 | ENUM_BITFIELD(machine_mode)enum machine_mode truncated_to_mode : 8; | ||||||
239 | }; | ||||||
240 | |||||||
241 | |||||||
242 | static vec<reg_stat_type> reg_stat; | ||||||
243 | |||||||
244 | /* One plus the highest pseudo for which we track REG_N_SETS. | ||||||
245 | regstat_init_n_sets_and_refs allocates the array for REG_N_SETS just once, | ||||||
246 | but during combine_split_insns new pseudos can be created. As we don't have | ||||||
247 | updated DF information in that case, it is hard to initialize the array | ||||||
248 | after growing. The combiner only cares about REG_N_SETS (regno) == 1, | ||||||
249 | so instead of growing the arrays, just assume all newly created pseudos | ||||||
250 | during combine might be set multiple times. */ | ||||||
251 | |||||||
252 | static unsigned int reg_n_sets_max; | ||||||
253 | |||||||
254 | /* Record the luid of the last insn that invalidated memory | ||||||
255 | (anything that writes memory, and subroutine calls, but not pushes). */ | ||||||
256 | |||||||
257 | static int mem_last_set; | ||||||
258 | |||||||
259 | /* Record the luid of the last CALL_INSN | ||||||
260 | so we can tell whether a potential combination crosses any calls. */ | ||||||
261 | |||||||
262 | static int last_call_luid; | ||||||
263 | |||||||
264 | /* When `subst' is called, this is the insn that is being modified | ||||||
265 | (by combining in a previous insn). The PATTERN of this insn | ||||||
266 | is still the old pattern partially modified and it should not be | ||||||
267 | looked at, but this may be used to examine the successors of the insn | ||||||
268 | to judge whether a simplification is valid. */ | ||||||
269 | |||||||
270 | static rtx_insn *subst_insn; | ||||||
271 | |||||||
272 | /* This is the lowest LUID that `subst' is currently dealing with. | ||||||
273 | get_last_value will not return a value if the register was set at or | ||||||
274 | after this LUID. If not for this mechanism, we could get confused if | ||||||
275 | I2 or I1 in try_combine were an insn that used the old value of a register | ||||||
276 | to obtain a new value. In that case, we might erroneously get the | ||||||
277 | new value of the register when we wanted the old one. */ | ||||||
278 | |||||||
279 | static int subst_low_luid; | ||||||
280 | |||||||
281 | /* This contains any hard registers that are used in newpat; reg_dead_at_p | ||||||
282 | must consider all these registers to be always live. */ | ||||||
283 | |||||||
284 | static HARD_REG_SET newpat_used_regs; | ||||||
285 | |||||||
286 | /* This is an insn to which a LOG_LINKS entry has been added. If this | ||||||
287 | insn is the earlier than I2 or I3, combine should rescan starting at | ||||||
288 | that location. */ | ||||||
289 | |||||||
290 | static rtx_insn *added_links_insn; | ||||||
291 | |||||||
292 | /* And similarly, for notes. */ | ||||||
293 | |||||||
294 | static rtx_insn *added_notes_insn; | ||||||
295 | |||||||
296 | /* Basic block in which we are performing combines. */ | ||||||
297 | static basic_block this_basic_block; | ||||||
298 | static bool optimize_this_for_speed_p; | ||||||
299 | |||||||
300 | |||||||
301 | /* Length of the currently allocated uid_insn_cost array. */ | ||||||
302 | |||||||
303 | static int max_uid_known; | ||||||
304 | |||||||
305 | /* The following array records the insn_cost for every insn | ||||||
306 | in the instruction stream. */ | ||||||
307 | |||||||
308 | static int *uid_insn_cost; | ||||||
309 | |||||||
310 | /* The following array records the LOG_LINKS for every insn in the | ||||||
311 | instruction stream as struct insn_link pointers. */ | ||||||
312 | |||||||
313 | struct insn_link { | ||||||
314 | rtx_insn *insn; | ||||||
315 | unsigned int regno; | ||||||
316 | struct insn_link *next; | ||||||
317 | }; | ||||||
318 | |||||||
319 | static struct insn_link **uid_log_links; | ||||||
320 | |||||||
321 | static inline int | ||||||
322 | insn_uid_check (const_rtx insn) | ||||||
323 | { | ||||||
324 | int uid = INSN_UID (insn); | ||||||
325 | gcc_checking_assert (uid <= max_uid_known)((void)(!(uid <= max_uid_known) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 325, __FUNCTION__), 0 : 0)); | ||||||
326 | return uid; | ||||||
327 | } | ||||||
328 | |||||||
329 | #define INSN_COST(INSN)(uid_insn_cost[insn_uid_check (INSN)]) (uid_insn_cost[insn_uid_check (INSN)]) | ||||||
330 | #define LOG_LINKS(INSN)(uid_log_links[insn_uid_check (INSN)]) (uid_log_links[insn_uid_check (INSN)]) | ||||||
331 | |||||||
332 | #define FOR_EACH_LOG_LINK(L, INSN)for ((L) = (uid_log_links[insn_uid_check (INSN)]); (L); (L) = (L)->next) \ | ||||||
333 | for ((L) = LOG_LINKS (INSN)(uid_log_links[insn_uid_check (INSN)]); (L); (L) = (L)->next) | ||||||
334 | |||||||
335 | /* Links for LOG_LINKS are allocated from this obstack. */ | ||||||
336 | |||||||
337 | static struct obstack insn_link_obstack; | ||||||
338 | |||||||
339 | /* Allocate a link. */ | ||||||
340 | |||||||
341 | static inline struct insn_link * | ||||||
342 | alloc_insn_link (rtx_insn *insn, unsigned int regno, struct insn_link *next) | ||||||
343 | { | ||||||
344 | struct insn_link *l | ||||||
345 | = (struct insn_link *) obstack_alloc (&insn_link_obstack,__extension__ ({ struct obstack *__h = (&insn_link_obstack ); __extension__ ({ struct obstack *__o = (__h); size_t __len = ((sizeof (struct insn_link))); if (__extension__ ({ struct obstack const *__o1 = (__o); (size_t) (__o1->chunk_limit - __o1->next_free); }) < __len) _obstack_newchunk (__o, __len ); ((void) ((__o)->next_free += (__len))); }); __extension__ ({ struct obstack *__o1 = (__h); void *__value = (void *) __o1 ->object_base; if (__o1->next_free == __value) __o1-> maybe_empty_object = 1; __o1->next_free = (sizeof (ptrdiff_t ) < sizeof (void *) ? ((__o1->object_base) + (((__o1-> next_free) - (__o1->object_base) + (__o1->alignment_mask )) & ~(__o1->alignment_mask))) : (char *) (((ptrdiff_t ) (__o1->next_free) + (__o1->alignment_mask)) & ~(__o1 ->alignment_mask))); if ((size_t) (__o1->next_free - (char *) __o1->chunk) > (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) __o1->next_free = __o1->chunk_limit ; __o1->object_base = __o1->next_free; __value; }); }) | ||||||
346 | sizeof (struct insn_link))__extension__ ({ struct obstack *__h = (&insn_link_obstack ); __extension__ ({ struct obstack *__o = (__h); size_t __len = ((sizeof (struct insn_link))); if (__extension__ ({ struct obstack const *__o1 = (__o); (size_t) (__o1->chunk_limit - __o1->next_free); }) < __len) _obstack_newchunk (__o, __len ); ((void) ((__o)->next_free += (__len))); }); __extension__ ({ struct obstack *__o1 = (__h); void *__value = (void *) __o1 ->object_base; if (__o1->next_free == __value) __o1-> maybe_empty_object = 1; __o1->next_free = (sizeof (ptrdiff_t ) < sizeof (void *) ? ((__o1->object_base) + (((__o1-> next_free) - (__o1->object_base) + (__o1->alignment_mask )) & ~(__o1->alignment_mask))) : (char *) (((ptrdiff_t ) (__o1->next_free) + (__o1->alignment_mask)) & ~(__o1 ->alignment_mask))); if ((size_t) (__o1->next_free - (char *) __o1->chunk) > (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) __o1->next_free = __o1->chunk_limit ; __o1->object_base = __o1->next_free; __value; }); }); | ||||||
347 | l->insn = insn; | ||||||
348 | l->regno = regno; | ||||||
349 | l->next = next; | ||||||
350 | return l; | ||||||
351 | } | ||||||
352 | |||||||
353 | /* Incremented for each basic block. */ | ||||||
354 | |||||||
355 | static int label_tick; | ||||||
356 | |||||||
357 | /* Reset to label_tick for each extended basic block in scanning order. */ | ||||||
358 | |||||||
359 | static int label_tick_ebb_start; | ||||||
360 | |||||||
361 | /* Mode used to compute significance in reg_stat[].nonzero_bits. It is the | ||||||
362 | largest integer mode that can fit in HOST_BITS_PER_WIDE_INT. */ | ||||||
363 | |||||||
364 | static scalar_int_mode nonzero_bits_mode; | ||||||
365 | |||||||
366 | /* Nonzero when reg_stat[].nonzero_bits and reg_stat[].sign_bit_copies can | ||||||
367 | be safely used. It is zero while computing them and after combine has | ||||||
368 | completed. This former test prevents propagating values based on | ||||||
369 | previously set values, which can be incorrect if a variable is modified | ||||||
370 | in a loop. */ | ||||||
371 | |||||||
372 | static int nonzero_sign_valid; | ||||||
373 | |||||||
374 | |||||||
375 | /* Record one modification to rtl structure | ||||||
376 | to be undone by storing old_contents into *where. */ | ||||||
377 | |||||||
378 | enum undo_kind { UNDO_RTX, UNDO_INT, UNDO_MODE, UNDO_LINKS }; | ||||||
379 | |||||||
380 | struct undo | ||||||
381 | { | ||||||
382 | struct undo *next; | ||||||
383 | enum undo_kind kind; | ||||||
384 | union { rtx r; int i; machine_mode m; struct insn_link *l; } old_contents; | ||||||
385 | union { rtx *r; int *i; int regno; struct insn_link **l; } where; | ||||||
386 | }; | ||||||
387 | |||||||
388 | /* Record a bunch of changes to be undone, up to MAX_UNDO of them. | ||||||
389 | num_undo says how many are currently recorded. | ||||||
390 | |||||||
391 | other_insn is nonzero if we have modified some other insn in the process | ||||||
392 | of working on subst_insn. It must be verified too. */ | ||||||
393 | |||||||
394 | struct undobuf | ||||||
395 | { | ||||||
396 | struct undo *undos; | ||||||
397 | struct undo *frees; | ||||||
398 | rtx_insn *other_insn; | ||||||
399 | }; | ||||||
400 | |||||||
401 | static struct undobuf undobuf; | ||||||
402 | |||||||
403 | /* Number of times the pseudo being substituted for | ||||||
404 | was found and replaced. */ | ||||||
405 | |||||||
406 | static int n_occurrences; | ||||||
407 | |||||||
408 | static rtx reg_nonzero_bits_for_combine (const_rtx, scalar_int_mode, | ||||||
409 | scalar_int_mode, | ||||||
410 | unsigned HOST_WIDE_INTlong *); | ||||||
411 | static rtx reg_num_sign_bit_copies_for_combine (const_rtx, scalar_int_mode, | ||||||
412 | scalar_int_mode, | ||||||
413 | unsigned int *); | ||||||
414 | static void do_SUBST (rtx *, rtx); | ||||||
415 | static void do_SUBST_INT (int *, int); | ||||||
416 | static void init_reg_last (void); | ||||||
417 | static void setup_incoming_promotions (rtx_insn *); | ||||||
418 | static void set_nonzero_bits_and_sign_copies (rtx, const_rtx, void *); | ||||||
419 | static int cant_combine_insn_p (rtx_insn *); | ||||||
420 | static int can_combine_p (rtx_insn *, rtx_insn *, rtx_insn *, rtx_insn *, | ||||||
421 | rtx_insn *, rtx_insn *, rtx *, rtx *); | ||||||
422 | static int combinable_i3pat (rtx_insn *, rtx *, rtx, rtx, rtx, int, int, rtx *); | ||||||
423 | static int contains_muldiv (rtx); | ||||||
424 | static rtx_insn *try_combine (rtx_insn *, rtx_insn *, rtx_insn *, rtx_insn *, | ||||||
425 | int *, rtx_insn *); | ||||||
426 | static void undo_all (void); | ||||||
427 | static void undo_commit (void); | ||||||
428 | static rtx *find_split_point (rtx *, rtx_insn *, bool); | ||||||
429 | static rtx subst (rtx, rtx, rtx, int, int, int); | ||||||
430 | static rtx combine_simplify_rtx (rtx, machine_mode, int, int); | ||||||
431 | static rtx simplify_if_then_else (rtx); | ||||||
432 | static rtx simplify_set (rtx); | ||||||
433 | static rtx simplify_logical (rtx); | ||||||
434 | static rtx expand_compound_operation (rtx); | ||||||
435 | static const_rtx expand_field_assignment (const_rtx); | ||||||
436 | static rtx make_extraction (machine_mode, rtx, HOST_WIDE_INTlong, | ||||||
437 | rtx, unsigned HOST_WIDE_INTlong, int, int, int); | ||||||
438 | static int get_pos_from_mask (unsigned HOST_WIDE_INTlong, | ||||||
439 | unsigned HOST_WIDE_INTlong *); | ||||||
440 | static rtx canon_reg_for_combine (rtx, rtx); | ||||||
441 | static rtx force_int_to_mode (rtx, scalar_int_mode, scalar_int_mode, | ||||||
442 | scalar_int_mode, unsigned HOST_WIDE_INTlong, int); | ||||||
443 | static rtx force_to_mode (rtx, machine_mode, | ||||||
444 | unsigned HOST_WIDE_INTlong, int); | ||||||
445 | static rtx if_then_else_cond (rtx, rtx *, rtx *); | ||||||
446 | static rtx known_cond (rtx, enum rtx_code, rtx, rtx); | ||||||
447 | static int rtx_equal_for_field_assignment_p (rtx, rtx, bool = false); | ||||||
448 | static rtx make_field_assignment (rtx); | ||||||
449 | static rtx apply_distributive_law (rtx); | ||||||
450 | static rtx distribute_and_simplify_rtx (rtx, int); | ||||||
451 | static rtx simplify_and_const_int_1 (scalar_int_mode, rtx, | ||||||
452 | unsigned HOST_WIDE_INTlong); | ||||||
453 | static rtx simplify_and_const_int (rtx, scalar_int_mode, rtx, | ||||||
454 | unsigned HOST_WIDE_INTlong); | ||||||
455 | static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INTlong *, enum rtx_code, | ||||||
456 | HOST_WIDE_INTlong, machine_mode, int *); | ||||||
457 | static rtx simplify_shift_const_1 (enum rtx_code, machine_mode, rtx, int); | ||||||
458 | static rtx simplify_shift_const (rtx, enum rtx_code, machine_mode, rtx, | ||||||
459 | int); | ||||||
460 | static int recog_for_combine (rtx *, rtx_insn *, rtx *); | ||||||
461 | static rtx gen_lowpart_for_combine (machine_mode, rtx); | ||||||
462 | static enum rtx_code simplify_compare_const (enum rtx_code, machine_mode, | ||||||
463 | rtx, rtx *); | ||||||
464 | static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *); | ||||||
465 | static void update_table_tick (rtx); | ||||||
466 | static void record_value_for_reg (rtx, rtx_insn *, rtx); | ||||||
467 | static void check_promoted_subreg (rtx_insn *, rtx); | ||||||
468 | static void record_dead_and_set_regs_1 (rtx, const_rtx, void *); | ||||||
469 | static void record_dead_and_set_regs (rtx_insn *); | ||||||
470 | static int get_last_value_validate (rtx *, rtx_insn *, int, int); | ||||||
471 | static rtx get_last_value (const_rtx); | ||||||
472 | static void reg_dead_at_p_1 (rtx, const_rtx, void *); | ||||||
473 | static int reg_dead_at_p (rtx, rtx_insn *); | ||||||
474 | static void move_deaths (rtx, rtx, int, rtx_insn *, rtx *); | ||||||
475 | static int reg_bitfield_target_p (rtx, rtx); | ||||||
476 | static void distribute_notes (rtx, rtx_insn *, rtx_insn *, rtx_insn *, rtx, rtx, rtx); | ||||||
477 | static void distribute_links (struct insn_link *); | ||||||
478 | static void mark_used_regs_combine (rtx); | ||||||
479 | static void record_promoted_value (rtx_insn *, rtx); | ||||||
480 | static bool unmentioned_reg_p (rtx, rtx); | ||||||
481 | static void record_truncated_values (rtx *, void *); | ||||||
482 | static bool reg_truncated_to_mode (machine_mode, const_rtx); | ||||||
483 | static rtx gen_lowpart_or_truncate (machine_mode, rtx); | ||||||
484 | |||||||
485 | |||||||
486 | /* It is not safe to use ordinary gen_lowpart in combine. | ||||||
487 | See comments in gen_lowpart_for_combine. */ | ||||||
488 | #undef RTL_HOOKS_GEN_LOWPARTgen_lowpart_for_combine | ||||||
489 | #define RTL_HOOKS_GEN_LOWPARTgen_lowpart_for_combine gen_lowpart_for_combine | ||||||
490 | |||||||
491 | /* Our implementation of gen_lowpart never emits a new pseudo. */ | ||||||
492 | #undef RTL_HOOKS_GEN_LOWPART_NO_EMITgen_lowpart_for_combine | ||||||
493 | #define RTL_HOOKS_GEN_LOWPART_NO_EMITgen_lowpart_for_combine gen_lowpart_for_combine | ||||||
494 | |||||||
495 | #undef RTL_HOOKS_REG_NONZERO_REG_BITSreg_nonzero_bits_for_combine | ||||||
496 | #define RTL_HOOKS_REG_NONZERO_REG_BITSreg_nonzero_bits_for_combine reg_nonzero_bits_for_combine | ||||||
497 | |||||||
498 | #undef RTL_HOOKS_REG_NUM_SIGN_BIT_COPIESreg_num_sign_bit_copies_for_combine | ||||||
499 | #define RTL_HOOKS_REG_NUM_SIGN_BIT_COPIESreg_num_sign_bit_copies_for_combine reg_num_sign_bit_copies_for_combine | ||||||
500 | |||||||
501 | #undef RTL_HOOKS_REG_TRUNCATED_TO_MODEreg_truncated_to_mode | ||||||
502 | #define RTL_HOOKS_REG_TRUNCATED_TO_MODEreg_truncated_to_mode reg_truncated_to_mode | ||||||
503 | |||||||
504 | static const struct rtl_hooks combine_rtl_hooks = RTL_HOOKS_INITIALIZER{ gen_lowpart_for_combine, gen_lowpart_for_combine, reg_nonzero_bits_for_combine , reg_num_sign_bit_copies_for_combine, reg_truncated_to_mode }; | ||||||
505 | |||||||
506 | |||||||
507 | /* Convenience wrapper for the canonicalize_comparison target hook. | ||||||
508 | Target hooks cannot use enum rtx_code. */ | ||||||
509 | static inline void | ||||||
510 | target_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1, | ||||||
511 | bool op0_preserve_value) | ||||||
512 | { | ||||||
513 | int code_int = (int)*code; | ||||||
514 | targetm.canonicalize_comparison (&code_int, op0, op1, op0_preserve_value); | ||||||
515 | *code = (enum rtx_code)code_int; | ||||||
516 | } | ||||||
517 | |||||||
518 | /* Try to split PATTERN found in INSN. This returns NULL_RTX if | ||||||
519 | PATTERN cannot be split. Otherwise, it returns an insn sequence. | ||||||
520 | This is a wrapper around split_insns which ensures that the | ||||||
521 | reg_stat vector is made larger if the splitter creates a new | ||||||
522 | register. */ | ||||||
523 | |||||||
524 | static rtx_insn * | ||||||
525 | combine_split_insns (rtx pattern, rtx_insn *insn) | ||||||
526 | { | ||||||
527 | rtx_insn *ret; | ||||||
528 | unsigned int nregs; | ||||||
529 | |||||||
530 | ret = split_insns (pattern, insn); | ||||||
531 | nregs = max_reg_num (); | ||||||
532 | if (nregs > reg_stat.length ()) | ||||||
533 | reg_stat.safe_grow_cleared (nregs, true); | ||||||
534 | return ret; | ||||||
535 | } | ||||||
536 | |||||||
537 | /* This is used by find_single_use to locate an rtx in LOC that | ||||||
538 | contains exactly one use of DEST, which is typically a REG. | ||||||
539 | It returns a pointer to the innermost rtx expression | ||||||
540 | containing DEST. Appearances of DEST that are being used to | ||||||
541 | totally replace it are not counted. */ | ||||||
542 | |||||||
543 | static rtx * | ||||||
544 | find_single_use_1 (rtx dest, rtx *loc) | ||||||
545 | { | ||||||
546 | rtx x = *loc; | ||||||
547 | enum rtx_code code = GET_CODE (x)((enum rtx_code) (x)->code); | ||||||
548 | rtx *result = NULLnullptr; | ||||||
549 | rtx *this_result; | ||||||
550 | int i; | ||||||
551 | const char *fmt; | ||||||
552 | |||||||
553 | switch (code) | ||||||
554 | { | ||||||
555 | case CONST: | ||||||
556 | case LABEL_REF: | ||||||
557 | case SYMBOL_REF: | ||||||
558 | CASE_CONST_ANYcase CONST_INT: case CONST_WIDE_INT: case CONST_POLY_INT: case CONST_DOUBLE: case CONST_FIXED: case CONST_VECTOR: | ||||||
559 | case CLOBBER: | ||||||
560 | return 0; | ||||||
561 | |||||||
562 | case SET: | ||||||
563 | /* If the destination is anything other than PC, a REG or a SUBREG | ||||||
564 | of a REG that occupies all of the REG, the insn uses DEST if | ||||||
565 | it is mentioned in the destination or the source. Otherwise, we | ||||||
566 | need just check the source. */ | ||||||
567 | if (GET_CODE (SET_DEST (x))((enum rtx_code) ((((x)->u.fld[0]).rt_rtx))->code) != PC | ||||||
568 | && !REG_P (SET_DEST (x))(((enum rtx_code) ((((x)->u.fld[0]).rt_rtx))->code) == REG ) | ||||||
569 | && ! (GET_CODE (SET_DEST (x))((enum rtx_code) ((((x)->u.fld[0]).rt_rtx))->code) == SUBREG | ||||||
570 | && REG_P (SUBREG_REG (SET_DEST (x)))(((enum rtx_code) (((((((x)->u.fld[0]).rt_rtx))->u.fld[ 0]).rt_rtx))->code) == REG) | ||||||
571 | && !read_modify_subreg_p (SET_DEST (x)(((x)->u.fld[0]).rt_rtx)))) | ||||||
572 | break; | ||||||
573 | |||||||
574 | return find_single_use_1 (dest, &SET_SRC (x)(((x)->u.fld[1]).rt_rtx)); | ||||||
575 | |||||||
576 | case MEM: | ||||||
577 | case SUBREG: | ||||||
578 | return find_single_use_1 (dest, &XEXP (x, 0)(((x)->u.fld[0]).rt_rtx)); | ||||||
579 | |||||||
580 | default: | ||||||
581 | break; | ||||||
582 | } | ||||||
583 | |||||||
584 | /* If it wasn't one of the common cases above, check each expression and | ||||||
585 | vector of this code. Look for a unique usage of DEST. */ | ||||||
586 | |||||||
587 | fmt = GET_RTX_FORMAT (code)(rtx_format[(int) (code)]); | ||||||
588 | for (i = GET_RTX_LENGTH (code)(rtx_length[(int) (code)]) - 1; i >= 0; i--) | ||||||
589 | { | ||||||
590 | if (fmt[i] == 'e') | ||||||
591 | { | ||||||
592 | if (dest == XEXP (x, i)(((x)->u.fld[i]).rt_rtx) | ||||||
593 | || (REG_P (dest)(((enum rtx_code) (dest)->code) == REG) && REG_P (XEXP (x, i))(((enum rtx_code) ((((x)->u.fld[i]).rt_rtx))->code) == REG ) | ||||||
594 | && REGNO (dest)(rhs_regno(dest)) == REGNO (XEXP (x, i))(rhs_regno((((x)->u.fld[i]).rt_rtx))))) | ||||||
595 | this_result = loc; | ||||||
596 | else | ||||||
597 | this_result = find_single_use_1 (dest, &XEXP (x, i)(((x)->u.fld[i]).rt_rtx)); | ||||||
598 | |||||||
599 | if (result == NULLnullptr) | ||||||
600 | result = this_result; | ||||||
601 | else if (this_result) | ||||||
602 | /* Duplicate usage. */ | ||||||
603 | return NULLnullptr; | ||||||
604 | } | ||||||
605 | else if (fmt[i] == 'E') | ||||||
606 | { | ||||||
607 | int j; | ||||||
608 | |||||||
609 | for (j = XVECLEN (x, i)(((((x)->u.fld[i]).rt_rtvec))->num_elem) - 1; j >= 0; j--) | ||||||
610 | { | ||||||
611 | if (XVECEXP (x, i, j)(((((x)->u.fld[i]).rt_rtvec))->elem[j]) == dest | ||||||
612 | || (REG_P (dest)(((enum rtx_code) (dest)->code) == REG) | ||||||
613 | && REG_P (XVECEXP (x, i, j))(((enum rtx_code) ((((((x)->u.fld[i]).rt_rtvec))->elem[ j]))->code) == REG) | ||||||
614 | && REGNO (XVECEXP (x, i, j))(rhs_regno((((((x)->u.fld[i]).rt_rtvec))->elem[j]))) == REGNO (dest)(rhs_regno(dest)))) | ||||||
615 | this_result = loc; | ||||||
616 | else | ||||||
617 | this_result = find_single_use_1 (dest, &XVECEXP (x, i, j)(((((x)->u.fld[i]).rt_rtvec))->elem[j])); | ||||||
618 | |||||||
619 | if (result == NULLnullptr) | ||||||
620 | result = this_result; | ||||||
621 | else if (this_result) | ||||||
622 | return NULLnullptr; | ||||||
623 | } | ||||||
624 | } | ||||||
625 | } | ||||||
626 | |||||||
627 | return result; | ||||||
628 | } | ||||||
629 | |||||||
630 | |||||||
631 | /* See if DEST, produced in INSN, is used only a single time in the | ||||||
632 | sequel. If so, return a pointer to the innermost rtx expression in which | ||||||
633 | it is used. | ||||||
634 | |||||||
635 | If PLOC is nonzero, *PLOC is set to the insn containing the single use. | ||||||
636 | |||||||
637 | Otherwise, we find the single use by finding an insn that has a | ||||||
638 | LOG_LINKS pointing at INSN and has a REG_DEAD note for DEST. If DEST is | ||||||
639 | only referenced once in that insn, we know that it must be the first | ||||||
640 | and last insn referencing DEST. */ | ||||||
641 | |||||||
642 | static rtx * | ||||||
643 | find_single_use (rtx dest, rtx_insn *insn, rtx_insn **ploc) | ||||||
644 | { | ||||||
645 | basic_block bb; | ||||||
646 | rtx_insn *next; | ||||||
647 | rtx *result; | ||||||
648 | struct insn_link *link; | ||||||
649 | |||||||
650 | if (!REG_P (dest)(((enum rtx_code) (dest)->code) == REG)) | ||||||
651 | return 0; | ||||||
652 | |||||||
653 | bb = BLOCK_FOR_INSN (insn); | ||||||
654 | for (next = NEXT_INSN (insn); | ||||||
655 | next && BLOCK_FOR_INSN (next) == bb; | ||||||
656 | next = NEXT_INSN (next)) | ||||||
657 | if (NONDEBUG_INSN_P (next)((((enum rtx_code) (next)->code) == INSN) || (((enum rtx_code ) (next)->code) == JUMP_INSN) || (((enum rtx_code) (next)-> code) == CALL_INSN)) && dead_or_set_p (next, dest)) | ||||||
658 | { | ||||||
659 | FOR_EACH_LOG_LINK (link, next)for ((link) = (uid_log_links[insn_uid_check (next)]); (link); (link) = (link)->next) | ||||||
660 | if (link->insn == insn && link->regno == REGNO (dest)(rhs_regno(dest))) | ||||||
661 | break; | ||||||
662 | |||||||
663 | if (link) | ||||||
664 | { | ||||||
665 | result = find_single_use_1 (dest, &PATTERN (next)); | ||||||
666 | if (ploc) | ||||||
667 | *ploc = next; | ||||||
668 | return result; | ||||||
669 | } | ||||||
670 | } | ||||||
671 | |||||||
672 | return 0; | ||||||
673 | } | ||||||
674 | |||||||
675 | /* Substitute NEWVAL, an rtx expression, into INTO, a place in some | ||||||
676 | insn. The substitution can be undone by undo_all. If INTO is already | ||||||
677 | set to NEWVAL, do not record this change. Because computing NEWVAL might | ||||||
678 | also call SUBST, we have to compute it before we put anything into | ||||||
679 | the undo table. */ | ||||||
680 | |||||||
681 | static void | ||||||
682 | do_SUBST (rtx *into, rtx newval) | ||||||
683 | { | ||||||
684 | struct undo *buf; | ||||||
685 | rtx oldval = *into; | ||||||
686 | |||||||
687 | if (oldval == newval) | ||||||
688 | return; | ||||||
689 | |||||||
690 | /* We'd like to catch as many invalid transformations here as | ||||||
691 | possible. Unfortunately, there are way too many mode changes | ||||||
692 | that are perfectly valid, so we'd waste too much effort for | ||||||
693 | little gain doing the checks here. Focus on catching invalid | ||||||
694 | transformations involving integer constants. */ | ||||||
695 | if (GET_MODE_CLASS (GET_MODE (oldval))((enum mode_class) mode_class[((machine_mode) (oldval)->mode )]) == MODE_INT | ||||||
696 | && CONST_INT_P (newval)(((enum rtx_code) (newval)->code) == CONST_INT)) | ||||||
697 | { | ||||||
698 | /* Sanity check that we're replacing oldval with a CONST_INT | ||||||
699 | that is a valid sign-extension for the original mode. */ | ||||||
700 | gcc_assert (INTVAL (newval)((void)(!(((newval)->u.hwint[0]) == trunc_int_for_mode ((( newval)->u.hwint[0]), ((machine_mode) (oldval)->mode))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 701, __FUNCTION__), 0 : 0)) | ||||||
701 | == trunc_int_for_mode (INTVAL (newval), GET_MODE (oldval)))((void)(!(((newval)->u.hwint[0]) == trunc_int_for_mode ((( newval)->u.hwint[0]), ((machine_mode) (oldval)->mode))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 701, __FUNCTION__), 0 : 0)); | ||||||
702 | |||||||
703 | /* Replacing the operand of a SUBREG or a ZERO_EXTEND with a | ||||||
704 | CONST_INT is not valid, because after the replacement, the | ||||||
705 | original mode would be gone. Unfortunately, we can't tell | ||||||
706 | when do_SUBST is called to replace the operand thereof, so we | ||||||
707 | perform this test on oldval instead, checking whether an | ||||||
708 | invalid replacement took place before we got here. */ | ||||||
709 | gcc_assert (!(GET_CODE (oldval) == SUBREG((void)(!(!(((enum rtx_code) (oldval)->code) == SUBREG && (((enum rtx_code) ((((oldval)->u.fld[0]).rt_rtx))->code ) == CONST_INT))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 710, __FUNCTION__), 0 : 0)) | ||||||
710 | && CONST_INT_P (SUBREG_REG (oldval))))((void)(!(!(((enum rtx_code) (oldval)->code) == SUBREG && (((enum rtx_code) ((((oldval)->u.fld[0]).rt_rtx))->code ) == CONST_INT))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 710, __FUNCTION__), 0 : 0)); | ||||||
711 | gcc_assert (!(GET_CODE (oldval) == ZERO_EXTEND((void)(!(!(((enum rtx_code) (oldval)->code) == ZERO_EXTEND && (((enum rtx_code) ((((oldval)->u.fld[0]).rt_rtx ))->code) == CONST_INT))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 712, __FUNCTION__), 0 : 0)) | ||||||
712 | && CONST_INT_P (XEXP (oldval, 0))))((void)(!(!(((enum rtx_code) (oldval)->code) == ZERO_EXTEND && (((enum rtx_code) ((((oldval)->u.fld[0]).rt_rtx ))->code) == CONST_INT))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 712, __FUNCTION__), 0 : 0)); | ||||||
713 | } | ||||||
714 | |||||||
715 | if (undobuf.frees) | ||||||
716 | buf = undobuf.frees, undobuf.frees = buf->next; | ||||||
717 | else | ||||||
718 | buf = XNEW (struct undo)((struct undo *) xmalloc (sizeof (struct undo))); | ||||||
719 | |||||||
720 | buf->kind = UNDO_RTX; | ||||||
721 | buf->where.r = into; | ||||||
722 | buf->old_contents.r = oldval; | ||||||
723 | *into = newval; | ||||||
724 | |||||||
725 | buf->next = undobuf.undos, undobuf.undos = buf; | ||||||
726 | } | ||||||
727 | |||||||
728 | #define SUBST(INTO, NEWVAL)do_SUBST (&(INTO), (NEWVAL)) do_SUBST (&(INTO), (NEWVAL)) | ||||||
729 | |||||||
730 | /* Similar to SUBST, but NEWVAL is an int expression. Note that substitution | ||||||
731 | for the value of a HOST_WIDE_INT value (including CONST_INT) is | ||||||
732 | not safe. */ | ||||||
733 | |||||||
734 | static void | ||||||
735 | do_SUBST_INT (int *into, int newval) | ||||||
736 | { | ||||||
737 | struct undo *buf; | ||||||
738 | int oldval = *into; | ||||||
739 | |||||||
740 | if (oldval == newval) | ||||||
741 | return; | ||||||
742 | |||||||
743 | if (undobuf.frees) | ||||||
744 | buf = undobuf.frees, undobuf.frees = buf->next; | ||||||
745 | else | ||||||
746 | buf = XNEW (struct undo)((struct undo *) xmalloc (sizeof (struct undo))); | ||||||
747 | |||||||
748 | buf->kind = UNDO_INT; | ||||||
749 | buf->where.i = into; | ||||||
750 | buf->old_contents.i = oldval; | ||||||
751 | *into = newval; | ||||||
752 | |||||||
753 | buf->next = undobuf.undos, undobuf.undos = buf; | ||||||
754 | } | ||||||
755 | |||||||
756 | #define SUBST_INT(INTO, NEWVAL)do_SUBST_INT (&(INTO), (NEWVAL)) do_SUBST_INT (&(INTO), (NEWVAL)) | ||||||
757 | |||||||
758 | /* Similar to SUBST, but just substitute the mode. This is used when | ||||||
759 | changing the mode of a pseudo-register, so that any other | ||||||
760 | references to the entry in the regno_reg_rtx array will change as | ||||||
761 | well. */ | ||||||
762 | |||||||
763 | static void | ||||||
764 | subst_mode (int regno, machine_mode newval) | ||||||
765 | { | ||||||
766 | struct undo *buf; | ||||||
767 | rtx reg = regno_reg_rtx[regno]; | ||||||
768 | machine_mode oldval = GET_MODE (reg)((machine_mode) (reg)->mode); | ||||||
769 | |||||||
770 | if (oldval == newval) | ||||||
771 | return; | ||||||
772 | |||||||
773 | if (undobuf.frees) | ||||||
774 | buf = undobuf.frees, undobuf.frees = buf->next; | ||||||
775 | else | ||||||
776 | buf = XNEW (struct undo)((struct undo *) xmalloc (sizeof (struct undo))); | ||||||
777 | |||||||
778 | buf->kind = UNDO_MODE; | ||||||
779 | buf->where.regno = regno; | ||||||
780 | buf->old_contents.m = oldval; | ||||||
781 | adjust_reg_mode (reg, newval); | ||||||
782 | |||||||
783 | buf->next = undobuf.undos, undobuf.undos = buf; | ||||||
784 | } | ||||||
785 | |||||||
786 | /* Similar to SUBST, but NEWVAL is a LOG_LINKS expression. */ | ||||||
787 | |||||||
788 | static void | ||||||
789 | do_SUBST_LINK (struct insn_link **into, struct insn_link *newval) | ||||||
790 | { | ||||||
791 | struct undo *buf; | ||||||
792 | struct insn_link * oldval = *into; | ||||||
793 | |||||||
794 | if (oldval == newval) | ||||||
795 | return; | ||||||
796 | |||||||
797 | if (undobuf.frees) | ||||||
798 | buf = undobuf.frees, undobuf.frees = buf->next; | ||||||
799 | else | ||||||
800 | buf = XNEW (struct undo)((struct undo *) xmalloc (sizeof (struct undo))); | ||||||
801 | |||||||
802 | buf->kind = UNDO_LINKS; | ||||||
803 | buf->where.l = into; | ||||||
804 | buf->old_contents.l = oldval; | ||||||
805 | *into = newval; | ||||||
806 | |||||||
807 | buf->next = undobuf.undos, undobuf.undos = buf; | ||||||
808 | } | ||||||
809 | |||||||
810 | #define SUBST_LINK(oldval, newval)do_SUBST_LINK (&oldval, newval) do_SUBST_LINK (&oldval, newval) | ||||||
811 | |||||||
812 | /* Subroutine of try_combine. Determine whether the replacement patterns | ||||||
813 | NEWPAT, NEWI2PAT and NEWOTHERPAT are cheaper according to insn_cost | ||||||
814 | than the original sequence I0, I1, I2, I3 and undobuf.other_insn. Note | ||||||
815 | that I0, I1 and/or NEWI2PAT may be NULL_RTX. Similarly, NEWOTHERPAT and | ||||||
816 | undobuf.other_insn may also both be NULL_RTX. Return false if the cost | ||||||
817 | of all the instructions can be estimated and the replacements are more | ||||||
818 | expensive than the original sequence. */ | ||||||
819 | |||||||
820 | static bool | ||||||
821 | combine_validate_cost (rtx_insn *i0, rtx_insn *i1, rtx_insn *i2, rtx_insn *i3, | ||||||
822 | rtx newpat, rtx newi2pat, rtx newotherpat) | ||||||
823 | { | ||||||
824 | int i0_cost, i1_cost, i2_cost, i3_cost; | ||||||
825 | int new_i2_cost, new_i3_cost; | ||||||
826 | int old_cost, new_cost; | ||||||
827 | |||||||
828 | /* Lookup the original insn_costs. */ | ||||||
829 | i2_cost = INSN_COST (i2)(uid_insn_cost[insn_uid_check (i2)]); | ||||||
830 | i3_cost = INSN_COST (i3)(uid_insn_cost[insn_uid_check (i3)]); | ||||||
831 | |||||||
832 | if (i1
| ||||||
833 | { | ||||||
834 | i1_cost = INSN_COST (i1)(uid_insn_cost[insn_uid_check (i1)]); | ||||||
835 | if (i0) | ||||||
836 | { | ||||||
837 | i0_cost = INSN_COST (i0)(uid_insn_cost[insn_uid_check (i0)]); | ||||||
838 | old_cost = (i0_cost > 0 && i1_cost > 0 && i2_cost > 0 && i3_cost > 0 | ||||||
839 | ? i0_cost + i1_cost + i2_cost + i3_cost : 0); | ||||||
840 | } | ||||||
841 | else | ||||||
842 | { | ||||||
843 | old_cost = (i1_cost > 0 && i2_cost > 0 && i3_cost > 0 | ||||||
844 | ? i1_cost + i2_cost + i3_cost : 0); | ||||||
845 | i0_cost = 0; | ||||||
846 | } | ||||||
847 | } | ||||||
848 | else | ||||||
849 | { | ||||||
850 | old_cost = (i2_cost > 0 && i3_cost > 0) ? i2_cost + i3_cost : 0; | ||||||
851 | i1_cost = i0_cost = 0; | ||||||
852 | } | ||||||
853 | |||||||
854 | /* If we have split a PARALLEL I2 to I1,I2, we have counted its cost twice; | ||||||
855 | correct that. */ | ||||||
856 | if (old_cost
| ||||||
857 | old_cost -= i1_cost; | ||||||
858 | |||||||
859 | |||||||
860 | /* Calculate the replacement insn_costs. */ | ||||||
861 | rtx tmp = PATTERN (i3); | ||||||
862 | PATTERN (i3) = newpat; | ||||||
863 | int tmpi = INSN_CODE (i3)(((i3)->u.fld[5]).rt_int); | ||||||
864 | INSN_CODE (i3)(((i3)->u.fld[5]).rt_int) = -1; | ||||||
865 | new_i3_cost = insn_cost (i3, optimize_this_for_speed_p); | ||||||
866 | PATTERN (i3) = tmp; | ||||||
867 | INSN_CODE (i3)(((i3)->u.fld[5]).rt_int) = tmpi; | ||||||
868 | if (newi2pat
| ||||||
869 | { | ||||||
870 | tmp = PATTERN (i2); | ||||||
871 | PATTERN (i2) = newi2pat; | ||||||
872 | tmpi = INSN_CODE (i2)(((i2)->u.fld[5]).rt_int); | ||||||
873 | INSN_CODE (i2)(((i2)->u.fld[5]).rt_int) = -1; | ||||||
874 | new_i2_cost = insn_cost (i2, optimize_this_for_speed_p); | ||||||
875 | PATTERN (i2) = tmp; | ||||||
876 | INSN_CODE (i2)(((i2)->u.fld[5]).rt_int) = tmpi; | ||||||
877 | new_cost = (new_i2_cost > 0 && new_i3_cost > 0) | ||||||
878 | ? new_i2_cost + new_i3_cost : 0; | ||||||
879 | } | ||||||
880 | else | ||||||
881 | { | ||||||
882 | new_cost = new_i3_cost; | ||||||
883 | new_i2_cost = 0; | ||||||
884 | } | ||||||
885 | |||||||
886 | if (undobuf.other_insn) | ||||||
887 | { | ||||||
888 | int old_other_cost, new_other_cost; | ||||||
889 | |||||||
890 | old_other_cost = INSN_COST (undobuf.other_insn)(uid_insn_cost[insn_uid_check (undobuf.other_insn)]); | ||||||
891 | tmp = PATTERN (undobuf.other_insn); | ||||||
892 | PATTERN (undobuf.other_insn) = newotherpat; | ||||||
893 | tmpi = INSN_CODE (undobuf.other_insn)(((undobuf.other_insn)->u.fld[5]).rt_int); | ||||||
894 | INSN_CODE (undobuf.other_insn)(((undobuf.other_insn)->u.fld[5]).rt_int) = -1; | ||||||
895 | new_other_cost = insn_cost (undobuf.other_insn, | ||||||
896 | optimize_this_for_speed_p); | ||||||
897 | PATTERN (undobuf.other_insn) = tmp; | ||||||
898 | INSN_CODE (undobuf.other_insn)(((undobuf.other_insn)->u.fld[5]).rt_int) = tmpi; | ||||||
899 | if (old_other_cost > 0 && new_other_cost > 0) | ||||||
900 | { | ||||||
901 | old_cost += old_other_cost; | ||||||
902 | new_cost += new_other_cost; | ||||||
903 | } | ||||||
904 | else | ||||||
905 | old_cost = 0; | ||||||
906 | } | ||||||
907 | |||||||
908 | /* Disallow this combination if both new_cost and old_cost are greater than | ||||||
909 | zero, and new_cost is greater than old cost. */ | ||||||
910 | int reject = old_cost
| ||||||
911 | |||||||
912 | if (dump_file) | ||||||
913 | { | ||||||
914 | fprintf (dump_file, "%s combination of insns ", | ||||||
915 | reject ? "rejecting" : "allowing"); | ||||||
916 | if (i0) | ||||||
917 | fprintf (dump_file, "%d, ", INSN_UID (i0)); | ||||||
918 | if (i1 && INSN_UID (i1) != INSN_UID (i2)) | ||||||
919 | fprintf (dump_file, "%d, ", INSN_UID (i1)); | ||||||
920 | fprintf (dump_file, "%d and %d\n", INSN_UID (i2), INSN_UID (i3)); | ||||||
921 | |||||||
922 | fprintf (dump_file, "original costs "); | ||||||
923 | if (i0) | ||||||
924 | fprintf (dump_file, "%d + ", i0_cost); | ||||||
925 | if (i1 && INSN_UID (i1) != INSN_UID (i2)) | ||||||
926 | fprintf (dump_file, "%d + ", i1_cost); | ||||||
927 | fprintf (dump_file, "%d + %d = %d\n", i2_cost, i3_cost, old_cost); | ||||||
928 | |||||||
929 | if (newi2pat) | ||||||
930 | fprintf (dump_file, "replacement costs %d + %d = %d\n", | ||||||
931 | new_i2_cost, new_i3_cost, new_cost); | ||||||
932 | else | ||||||
933 | fprintf (dump_file, "replacement cost %d\n", new_cost); | ||||||
934 | } | ||||||
935 | |||||||
936 | if (reject
| ||||||
937 | return false; | ||||||
938 | |||||||
939 | /* Update the uid_insn_cost array with the replacement costs. */ | ||||||
940 | INSN_COST (i2)(uid_insn_cost[insn_uid_check (i2)]) = new_i2_cost; | ||||||
941 | INSN_COST (i3)(uid_insn_cost[insn_uid_check (i3)]) = new_i3_cost; | ||||||
942 | if (i1
| ||||||
943 | { | ||||||
944 | INSN_COST (i1)(uid_insn_cost[insn_uid_check (i1)]) = 0; | ||||||
945 | if (i0) | ||||||
946 | INSN_COST (i0)(uid_insn_cost[insn_uid_check (i0)]) = 0; | ||||||
947 | } | ||||||
948 | |||||||
949 | return true; | ||||||
950 | } | ||||||
951 | |||||||
952 | |||||||
953 | /* Delete any insns that copy a register to itself. | ||||||
954 | Return true if the CFG was changed. */ | ||||||
955 | |||||||
956 | static bool | ||||||
957 | delete_noop_moves (void) | ||||||
958 | { | ||||||
959 | rtx_insn *insn, *next; | ||||||
960 | basic_block bb; | ||||||
961 | |||||||
962 | bool edges_deleted = false; | ||||||
963 | |||||||
964 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | ||||||
965 | { | ||||||
966 | for (insn = BB_HEAD (bb)(bb)->il.x.head_; insn != NEXT_INSN (BB_END (bb)(bb)->il.x.rtl->end_); insn = next) | ||||||
967 | { | ||||||
968 | next = NEXT_INSN (insn); | ||||||
969 | if (INSN_P (insn)(((((enum rtx_code) (insn)->code) == INSN) || (((enum rtx_code ) (insn)->code) == JUMP_INSN) || (((enum rtx_code) (insn)-> code) == CALL_INSN)) || (((enum rtx_code) (insn)->code) == DEBUG_INSN)) && noop_move_p (insn)) | ||||||
970 | { | ||||||
971 | if (dump_file) | ||||||
972 | fprintf (dump_file, "deleting noop move %d\n", INSN_UID (insn)); | ||||||
973 | |||||||
974 | edges_deleted |= delete_insn_and_edges (insn); | ||||||
975 | } | ||||||
976 | } | ||||||
977 | } | ||||||
978 | |||||||
979 | return edges_deleted; | ||||||
980 | } | ||||||
981 | |||||||
982 | |||||||
983 | /* Return false if we do not want to (or cannot) combine DEF. */ | ||||||
984 | static bool | ||||||
985 | can_combine_def_p (df_ref def) | ||||||
986 | { | ||||||
987 | /* Do not consider if it is pre/post modification in MEM. */ | ||||||
988 | if (DF_REF_FLAGS (def)((def)->base.flags) & DF_REF_PRE_POST_MODIFY) | ||||||
989 | return false; | ||||||
990 | |||||||
991 | unsigned int regno = DF_REF_REGNO (def)((def)->base.regno); | ||||||
992 | |||||||
993 | /* Do not combine frame pointer adjustments. */ | ||||||
994 | if ((regno == FRAME_POINTER_REGNUM19 | ||||||
995 | && (!reload_completed || frame_pointer_needed((&x_rtl)->frame_pointer_needed))) | ||||||
996 | || (!HARD_FRAME_POINTER_IS_FRAME_POINTER(6 == 19) | ||||||
997 | && regno == HARD_FRAME_POINTER_REGNUM6 | ||||||
998 | && (!reload_completed || frame_pointer_needed((&x_rtl)->frame_pointer_needed))) | ||||||
999 | || (FRAME_POINTER_REGNUM19 != ARG_POINTER_REGNUM16 | ||||||
1000 | && regno == ARG_POINTER_REGNUM16 && fixed_regs(this_target_hard_regs->x_fixed_regs)[regno])) | ||||||
1001 | return false; | ||||||
1002 | |||||||
1003 | return true; | ||||||
1004 | } | ||||||
1005 | |||||||
1006 | /* Return false if we do not want to (or cannot) combine USE. */ | ||||||
1007 | static bool | ||||||
1008 | can_combine_use_p (df_ref use) | ||||||
1009 | { | ||||||
1010 | /* Do not consider the usage of the stack pointer by function call. */ | ||||||
1011 | if (DF_REF_FLAGS (use)((use)->base.flags) & DF_REF_CALL_STACK_USAGE) | ||||||
1012 | return false; | ||||||
1013 | |||||||
1014 | return true; | ||||||
1015 | } | ||||||
1016 | |||||||
1017 | /* Fill in log links field for all insns. */ | ||||||
1018 | |||||||
1019 | static void | ||||||
1020 | create_log_links (void) | ||||||
1021 | { | ||||||
1022 | basic_block bb; | ||||||
1023 | rtx_insn **next_use; | ||||||
1024 | rtx_insn *insn; | ||||||
1025 | df_ref def, use; | ||||||
1026 | |||||||
1027 | next_use = XCNEWVEC (rtx_insn *, max_reg_num ())((rtx_insn * *) xcalloc ((max_reg_num ()), sizeof (rtx_insn * ))); | ||||||
1028 | |||||||
1029 | /* Pass through each block from the end, recording the uses of each | ||||||
1030 | register and establishing log links when def is encountered. | ||||||
1031 | Note that we do not clear next_use array in order to save time, | ||||||
1032 | so we have to test whether the use is in the same basic block as def. | ||||||
1033 | |||||||
1034 | There are a few cases below when we do not consider the definition or | ||||||
1035 | usage -- these are taken from original flow.c did. Don't ask me why it is | ||||||
1036 | done this way; I don't know and if it works, I don't want to know. */ | ||||||
1037 | |||||||
1038 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | ||||||
1039 | { | ||||||
1040 | FOR_BB_INSNS_REVERSE (bb, insn)for ((insn) = (bb)->il.x.rtl->end_; (insn) && ( insn) != PREV_INSN ((bb)->il.x.head_); (insn) = PREV_INSN ( insn)) | ||||||
1041 | { | ||||||
1042 | if (!NONDEBUG_INSN_P (insn)((((enum rtx_code) (insn)->code) == INSN) || (((enum rtx_code ) (insn)->code) == JUMP_INSN) || (((enum rtx_code) (insn)-> code) == CALL_INSN))) | ||||||
1043 | continue; | ||||||
1044 | |||||||
1045 | /* Log links are created only once. */ | ||||||
1046 | gcc_assert (!LOG_LINKS (insn))((void)(!(!(uid_log_links[insn_uid_check (insn)])) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1046, __FUNCTION__), 0 : 0)); | ||||||
1047 | |||||||
1048 | FOR_EACH_INSN_DEF (def, insn)for (def = (((df->insns[(INSN_UID (insn))]))->defs); def ; def = ((def)->base.next_loc)) | ||||||
1049 | { | ||||||
1050 | unsigned int regno = DF_REF_REGNO (def)((def)->base.regno); | ||||||
1051 | rtx_insn *use_insn; | ||||||
1052 | |||||||
1053 | if (!next_use[regno]) | ||||||
1054 | continue; | ||||||
1055 | |||||||
1056 | if (!can_combine_def_p (def)) | ||||||
1057 | continue; | ||||||
1058 | |||||||
1059 | use_insn = next_use[regno]; | ||||||
1060 | next_use[regno] = NULLnullptr; | ||||||
1061 | |||||||
1062 | if (BLOCK_FOR_INSN (use_insn) != bb) | ||||||
1063 | continue; | ||||||
1064 | |||||||
1065 | /* flow.c claimed: | ||||||
1066 | |||||||
1067 | We don't build a LOG_LINK for hard registers contained | ||||||
1068 | in ASM_OPERANDs. If these registers get replaced, | ||||||
1069 | we might wind up changing the semantics of the insn, | ||||||
1070 | even if reload can make what appear to be valid | ||||||
1071 | assignments later. */ | ||||||
1072 | if (regno < FIRST_PSEUDO_REGISTER76 | ||||||
1073 | && asm_noperands (PATTERN (use_insn)) >= 0) | ||||||
1074 | continue; | ||||||
1075 | |||||||
1076 | /* Don't add duplicate links between instructions. */ | ||||||
1077 | struct insn_link *links; | ||||||
1078 | FOR_EACH_LOG_LINK (links, use_insn)for ((links) = (uid_log_links[insn_uid_check (use_insn)]); (links ); (links) = (links)->next) | ||||||
1079 | if (insn == links->insn && regno == links->regno) | ||||||
1080 | break; | ||||||
1081 | |||||||
1082 | if (!links) | ||||||
1083 | LOG_LINKS (use_insn)(uid_log_links[insn_uid_check (use_insn)]) | ||||||
1084 | = alloc_insn_link (insn, regno, LOG_LINKS (use_insn)(uid_log_links[insn_uid_check (use_insn)])); | ||||||
1085 | } | ||||||
1086 | |||||||
1087 | FOR_EACH_INSN_USE (use, insn)for (use = (((df->insns[(INSN_UID (insn))]))->uses); use ; use = ((use)->base.next_loc)) | ||||||
1088 | if (can_combine_use_p (use)) | ||||||
1089 | next_use[DF_REF_REGNO (use)((use)->base.regno)] = insn; | ||||||
1090 | } | ||||||
1091 | } | ||||||
1092 | |||||||
1093 | free (next_use); | ||||||
1094 | } | ||||||
1095 | |||||||
1096 | /* Walk the LOG_LINKS of insn B to see if we find a reference to A. Return | ||||||
1097 | true if we found a LOG_LINK that proves that A feeds B. This only works | ||||||
1098 | if there are no instructions between A and B which could have a link | ||||||
1099 | depending on A, since in that case we would not record a link for B. */ | ||||||
1100 | |||||||
1101 | static bool | ||||||
1102 | insn_a_feeds_b (rtx_insn *a, rtx_insn *b) | ||||||
1103 | { | ||||||
1104 | struct insn_link *links; | ||||||
1105 | FOR_EACH_LOG_LINK (links, b)for ((links) = (uid_log_links[insn_uid_check (b)]); (links); ( links) = (links)->next) | ||||||
1106 | if (links->insn == a) | ||||||
1107 | return true; | ||||||
1108 | return false; | ||||||
1109 | } | ||||||
1110 | |||||||
1111 | /* Main entry point for combiner. F is the first insn of the function. | ||||||
1112 | NREGS is the first unused pseudo-reg number. | ||||||
1113 | |||||||
1114 | Return nonzero if the CFG was changed (e.g. if the combiner has | ||||||
1115 | turned an indirect jump instruction into a direct jump). */ | ||||||
1116 | static int | ||||||
1117 | combine_instructions (rtx_insn *f, unsigned int nregs) | ||||||
1118 | { | ||||||
1119 | rtx_insn *insn, *next; | ||||||
1120 | struct insn_link *links, *nextlinks; | ||||||
1121 | rtx_insn *first; | ||||||
1122 | basic_block last_bb; | ||||||
1123 | |||||||
1124 | int new_direct_jump_p = 0; | ||||||
1125 | |||||||
1126 | for (first = f; first && !NONDEBUG_INSN_P (first)((((enum rtx_code) (first)->code) == INSN) || (((enum rtx_code ) (first)->code) == JUMP_INSN) || (((enum rtx_code) (first )->code) == CALL_INSN)); ) | ||||||
1127 | first = NEXT_INSN (first); | ||||||
1128 | if (!first) | ||||||
1129 | return 0; | ||||||
1130 | |||||||
1131 | combine_attempts = 0; | ||||||
1132 | combine_merges = 0; | ||||||
1133 | combine_extras = 0; | ||||||
1134 | combine_successes = 0; | ||||||
1135 | |||||||
1136 | rtl_hooks = combine_rtl_hooks; | ||||||
1137 | |||||||
1138 | reg_stat.safe_grow_cleared (nregs, true); | ||||||
1139 | |||||||
1140 | init_recog_no_volatile (); | ||||||
1141 | |||||||
1142 | /* Allocate array for insn info. */ | ||||||
1143 | max_uid_known = get_max_uid (); | ||||||
1144 | uid_log_links = XCNEWVEC (struct insn_link *, max_uid_known + 1)((struct insn_link * *) xcalloc ((max_uid_known + 1), sizeof ( struct insn_link *))); | ||||||
1145 | uid_insn_cost = XCNEWVEC (int, max_uid_known + 1)((int *) xcalloc ((max_uid_known + 1), sizeof (int))); | ||||||
1146 | gcc_obstack_init (&insn_link_obstack)_obstack_begin (((&insn_link_obstack)), (memory_block_pool ::block_size), (0), (mempool_obstack_chunk_alloc), (mempool_obstack_chunk_free )); | ||||||
1147 | |||||||
1148 | nonzero_bits_mode = int_mode_for_size (HOST_BITS_PER_WIDE_INT64, 0).require (); | ||||||
1149 | |||||||
1150 | /* Don't use reg_stat[].nonzero_bits when computing it. This can cause | ||||||
1151 | problems when, for example, we have j <<= 1 in a loop. */ | ||||||
1152 | |||||||
1153 | nonzero_sign_valid = 0; | ||||||
1154 | label_tick = label_tick_ebb_start = 1; | ||||||
1155 | |||||||
1156 | /* Scan all SETs and see if we can deduce anything about what | ||||||
1157 | bits are known to be zero for some registers and how many copies | ||||||
1158 | of the sign bit are known to exist for those registers. | ||||||
1159 | |||||||
1160 | Also set any known values so that we can use it while searching | ||||||
1161 | for what bits are known to be set. */ | ||||||
1162 | |||||||
1163 | setup_incoming_promotions (first); | ||||||
1164 | /* Allow the entry block and the first block to fall into the same EBB. | ||||||
1165 | Conceptually the incoming promotions are assigned to the entry block. */ | ||||||
1166 | last_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr); | ||||||
1167 | |||||||
1168 | create_log_links (); | ||||||
1169 | FOR_EACH_BB_FN (this_basic_block, cfun)for (this_basic_block = ((cfun + 0))->cfg->x_entry_block_ptr ->next_bb; this_basic_block != ((cfun + 0))->cfg->x_exit_block_ptr ; this_basic_block = this_basic_block->next_bb) | ||||||
1170 | { | ||||||
1171 | optimize_this_for_speed_p = optimize_bb_for_speed_p (this_basic_block); | ||||||
1172 | last_call_luid = 0; | ||||||
1173 | mem_last_set = -1; | ||||||
1174 | |||||||
1175 | label_tick++; | ||||||
1176 | if (!single_pred_p (this_basic_block) | ||||||
1177 | || single_pred (this_basic_block) != last_bb) | ||||||
1178 | label_tick_ebb_start = label_tick; | ||||||
1179 | last_bb = this_basic_block; | ||||||
1180 | |||||||
1181 | FOR_BB_INSNS (this_basic_block, insn)for ((insn) = (this_basic_block)->il.x.head_; (insn) && (insn) != NEXT_INSN ((this_basic_block)->il.x.rtl->end_ ); (insn) = NEXT_INSN (insn)) | ||||||
1182 | if (INSN_P (insn)(((((enum rtx_code) (insn)->code) == INSN) || (((enum rtx_code ) (insn)->code) == JUMP_INSN) || (((enum rtx_code) (insn)-> code) == CALL_INSN)) || (((enum rtx_code) (insn)->code) == DEBUG_INSN)) && BLOCK_FOR_INSN (insn)) | ||||||
1183 | { | ||||||
1184 | rtx links; | ||||||
1185 | |||||||
1186 | subst_low_luid = DF_INSN_LUID (insn)((((df->insns[(INSN_UID (insn))]))->luid)); | ||||||
1187 | subst_insn = insn; | ||||||
1188 | |||||||
1189 | note_stores (insn, set_nonzero_bits_and_sign_copies, insn); | ||||||
1190 | record_dead_and_set_regs (insn); | ||||||
1191 | |||||||
1192 | if (AUTO_INC_DEC0) | ||||||
1193 | for (links = REG_NOTES (insn)(((insn)->u.fld[6]).rt_rtx); links; links = XEXP (links, 1)(((links)->u.fld[1]).rt_rtx)) | ||||||
1194 | if (REG_NOTE_KIND (links)((enum reg_note) ((machine_mode) (links)->mode)) == REG_INC) | ||||||
1195 | set_nonzero_bits_and_sign_copies (XEXP (links, 0)(((links)->u.fld[0]).rt_rtx), NULL_RTX(rtx) 0, | ||||||
1196 | insn); | ||||||
1197 | |||||||
1198 | /* Record the current insn_cost of this instruction. */ | ||||||
1199 | INSN_COST (insn)(uid_insn_cost[insn_uid_check (insn)]) = insn_cost (insn, optimize_this_for_speed_p); | ||||||
1200 | if (dump_file) | ||||||
1201 | { | ||||||
1202 | fprintf (dump_file, "insn_cost %d for ", INSN_COST (insn)(uid_insn_cost[insn_uid_check (insn)])); | ||||||
1203 | dump_insn_slim (dump_file, insn); | ||||||
1204 | } | ||||||
1205 | } | ||||||
1206 | } | ||||||
1207 | |||||||
1208 | nonzero_sign_valid = 1; | ||||||
1209 | |||||||
1210 | /* Now scan all the insns in forward order. */ | ||||||
1211 | label_tick = label_tick_ebb_start = 1; | ||||||
1212 | init_reg_last (); | ||||||
1213 | setup_incoming_promotions (first); | ||||||
1214 | last_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr); | ||||||
1215 | int max_combine = param_max_combine_insnsglobal_options.x_param_max_combine_insns; | ||||||
1216 | |||||||
1217 | FOR_EACH_BB_FN (this_basic_block, cfun)for (this_basic_block = ((cfun + 0))->cfg->x_entry_block_ptr ->next_bb; this_basic_block != ((cfun + 0))->cfg->x_exit_block_ptr ; this_basic_block = this_basic_block->next_bb) | ||||||
1218 | { | ||||||
1219 | rtx_insn *last_combined_insn = NULLnullptr; | ||||||
1220 | |||||||
1221 | /* Ignore instruction combination in basic blocks that are going to | ||||||
1222 | be removed as unreachable anyway. See PR82386. */ | ||||||
1223 | if (EDGE_COUNT (this_basic_block->preds)vec_safe_length (this_basic_block->preds) == 0) | ||||||
1224 | continue; | ||||||
1225 | |||||||
1226 | optimize_this_for_speed_p = optimize_bb_for_speed_p (this_basic_block); | ||||||
1227 | last_call_luid = 0; | ||||||
1228 | mem_last_set = -1; | ||||||
1229 | |||||||
1230 | label_tick++; | ||||||
1231 | if (!single_pred_p (this_basic_block) | ||||||
1232 | || single_pred (this_basic_block) != last_bb) | ||||||
1233 | label_tick_ebb_start = label_tick; | ||||||
1234 | last_bb = this_basic_block; | ||||||
1235 | |||||||
1236 | rtl_profile_for_bb (this_basic_block); | ||||||
1237 | for (insn = BB_HEAD (this_basic_block)(this_basic_block)->il.x.head_; | ||||||
1238 | insn != NEXT_INSN (BB_END (this_basic_block)(this_basic_block)->il.x.rtl->end_); | ||||||
1239 | insn = next ? next : NEXT_INSN (insn)) | ||||||
1240 | { | ||||||
1241 | next = 0; | ||||||
1242 | if (!NONDEBUG_INSN_P (insn)((((enum rtx_code) (insn)->code) == INSN) || (((enum rtx_code ) (insn)->code) == JUMP_INSN) || (((enum rtx_code) (insn)-> code) == CALL_INSN))) | ||||||
1243 | continue; | ||||||
1244 | |||||||
1245 | while (last_combined_insn | ||||||
1246 | && (!NONDEBUG_INSN_P (last_combined_insn)((((enum rtx_code) (last_combined_insn)->code) == INSN) || (((enum rtx_code) (last_combined_insn)->code) == JUMP_INSN ) || (((enum rtx_code) (last_combined_insn)->code) == CALL_INSN )) | ||||||
1247 | || last_combined_insn->deleted ())) | ||||||
1248 | last_combined_insn = PREV_INSN (last_combined_insn); | ||||||
1249 | if (last_combined_insn == NULL_RTX(rtx) 0 | ||||||
1250 | || BLOCK_FOR_INSN (last_combined_insn) != this_basic_block | ||||||
1251 | || DF_INSN_LUID (last_combined_insn)((((df->insns[(INSN_UID (last_combined_insn))]))->luid) ) <= DF_INSN_LUID (insn)((((df->insns[(INSN_UID (insn))]))->luid))) | ||||||
1252 | last_combined_insn = insn; | ||||||
1253 | |||||||
1254 | /* See if we know about function return values before this | ||||||
1255 | insn based upon SUBREG flags. */ | ||||||
1256 | check_promoted_subreg (insn, PATTERN (insn)); | ||||||
1257 | |||||||
1258 | /* See if we can find hardregs and subreg of pseudos in | ||||||
1259 | narrower modes. This could help turning TRUNCATEs | ||||||
1260 | into SUBREGs. */ | ||||||
1261 | note_uses (&PATTERN (insn), record_truncated_values, NULLnullptr); | ||||||
1262 | |||||||
1263 | /* Try this insn with each insn it links back to. */ | ||||||
1264 | |||||||
1265 | FOR_EACH_LOG_LINK (links, insn)for ((links) = (uid_log_links[insn_uid_check (insn)]); (links ); (links) = (links)->next) | ||||||
1266 | if ((next = try_combine (insn, links->insn, NULLnullptr, | ||||||
1267 | NULLnullptr, &new_direct_jump_p, | ||||||
1268 | last_combined_insn)) != 0) | ||||||
1269 | { | ||||||
1270 | statistics_counter_event (cfun(cfun + 0), "two-insn combine", 1); | ||||||
1271 | goto retry; | ||||||
1272 | } | ||||||
1273 | |||||||
1274 | /* Try each sequence of three linked insns ending with this one. */ | ||||||
1275 | |||||||
1276 | if (max_combine >= 3) | ||||||
1277 | FOR_EACH_LOG_LINK (links, insn)for ((links) = (uid_log_links[insn_uid_check (insn)]); (links ); (links) = (links)->next) | ||||||
1278 | { | ||||||
1279 | rtx_insn *link = links->insn; | ||||||
1280 | |||||||
1281 | /* If the linked insn has been replaced by a note, then there | ||||||
1282 | is no point in pursuing this chain any further. */ | ||||||
1283 | if (NOTE_P (link)(((enum rtx_code) (link)->code) == NOTE)) | ||||||
1284 | continue; | ||||||
1285 | |||||||
1286 | FOR_EACH_LOG_LINK (nextlinks, link)for ((nextlinks) = (uid_log_links[insn_uid_check (link)]); (nextlinks ); (nextlinks) = (nextlinks)->next) | ||||||
1287 | if ((next = try_combine (insn, link, nextlinks->insn, | ||||||
1288 | NULLnullptr, &new_direct_jump_p, | ||||||
1289 | last_combined_insn)) != 0) | ||||||
1290 | { | ||||||
1291 | statistics_counter_event (cfun(cfun + 0), "three-insn combine", 1); | ||||||
1292 | goto retry; | ||||||
1293 | } | ||||||
1294 | } | ||||||
1295 | |||||||
1296 | /* Try combining an insn with two different insns whose results it | ||||||
1297 | uses. */ | ||||||
1298 | if (max_combine >= 3) | ||||||
1299 | FOR_EACH_LOG_LINK (links, insn)for ((links) = (uid_log_links[insn_uid_check (insn)]); (links ); (links) = (links)->next) | ||||||
1300 | for (nextlinks = links->next; nextlinks; | ||||||
1301 | nextlinks = nextlinks->next) | ||||||
1302 | if ((next = try_combine (insn, links->insn, | ||||||
1303 | nextlinks->insn, NULLnullptr, | ||||||
1304 | &new_direct_jump_p, | ||||||
1305 | last_combined_insn)) != 0) | ||||||
1306 | |||||||
1307 | { | ||||||
1308 | statistics_counter_event (cfun(cfun + 0), "three-insn combine", 1); | ||||||
1309 | goto retry; | ||||||
1310 | } | ||||||
1311 | |||||||
1312 | /* Try four-instruction combinations. */ | ||||||
1313 | if (max_combine >= 4) | ||||||
1314 | FOR_EACH_LOG_LINK (links, insn)for ((links) = (uid_log_links[insn_uid_check (insn)]); (links ); (links) = (links)->next) | ||||||
1315 | { | ||||||
1316 | struct insn_link *next1; | ||||||
1317 | rtx_insn *link = links->insn; | ||||||
1318 | |||||||
1319 | /* If the linked insn has been replaced by a note, then there | ||||||
1320 | is no point in pursuing this chain any further. */ | ||||||
1321 | if (NOTE_P (link)(((enum rtx_code) (link)->code) == NOTE)) | ||||||
1322 | continue; | ||||||
1323 | |||||||
1324 | FOR_EACH_LOG_LINK (next1, link)for ((next1) = (uid_log_links[insn_uid_check (link)]); (next1 ); (next1) = (next1)->next) | ||||||
1325 | { | ||||||
1326 | rtx_insn *link1 = next1->insn; | ||||||
1327 | if (NOTE_P (link1)(((enum rtx_code) (link1)->code) == NOTE)) | ||||||
1328 | continue; | ||||||
1329 | /* I0 -> I1 -> I2 -> I3. */ | ||||||
1330 | FOR_EACH_LOG_LINK (nextlinks, link1)for ((nextlinks) = (uid_log_links[insn_uid_check (link1)]); ( nextlinks); (nextlinks) = (nextlinks)->next) | ||||||
1331 | if ((next = try_combine (insn, link, link1, | ||||||
1332 | nextlinks->insn, | ||||||
1333 | &new_direct_jump_p, | ||||||
1334 | last_combined_insn)) != 0) | ||||||
1335 | { | ||||||
1336 | statistics_counter_event (cfun(cfun + 0), "four-insn combine", 1); | ||||||
1337 | goto retry; | ||||||
1338 | } | ||||||
1339 | /* I0, I1 -> I2, I2 -> I3. */ | ||||||
1340 | for (nextlinks = next1->next; nextlinks; | ||||||
1341 | nextlinks = nextlinks->next) | ||||||
1342 | if ((next = try_combine (insn, link, link1, | ||||||
1343 | nextlinks->insn, | ||||||
1344 | &new_direct_jump_p, | ||||||
1345 | last_combined_insn)) != 0) | ||||||
1346 | { | ||||||
1347 | statistics_counter_event (cfun(cfun + 0), "four-insn combine", 1); | ||||||
1348 | goto retry; | ||||||
1349 | } | ||||||
1350 | } | ||||||
1351 | |||||||
1352 | for (next1 = links->next; next1; next1 = next1->next) | ||||||
1353 | { | ||||||
1354 | rtx_insn *link1 = next1->insn; | ||||||
1355 | if (NOTE_P (link1)(((enum rtx_code) (link1)->code) == NOTE)) | ||||||
1356 | continue; | ||||||
1357 | /* I0 -> I2; I1, I2 -> I3. */ | ||||||
1358 | FOR_EACH_LOG_LINK (nextlinks, link)for ((nextlinks) = (uid_log_links[insn_uid_check (link)]); (nextlinks ); (nextlinks) = (nextlinks)->next) | ||||||
1359 | if ((next = try_combine (insn, link, link1, | ||||||
1360 | nextlinks->insn, | ||||||
1361 | &new_direct_jump_p, | ||||||
1362 | last_combined_insn)) != 0) | ||||||
1363 | { | ||||||
1364 | statistics_counter_event (cfun(cfun + 0), "four-insn combine", 1); | ||||||
1365 | goto retry; | ||||||
1366 | } | ||||||
1367 | /* I0 -> I1; I1, I2 -> I3. */ | ||||||
1368 | FOR_EACH_LOG_LINK (nextlinks, link1)for ((nextlinks) = (uid_log_links[insn_uid_check (link1)]); ( nextlinks); (nextlinks) = (nextlinks)->next) | ||||||
1369 | if ((next = try_combine (insn, link, link1, | ||||||
1370 | nextlinks->insn, | ||||||
1371 | &new_direct_jump_p, | ||||||
1372 | last_combined_insn)) != 0) | ||||||
1373 | { | ||||||
1374 | statistics_counter_event (cfun(cfun + 0), "four-insn combine", 1); | ||||||
1375 | goto retry; | ||||||
1376 | } | ||||||
1377 | } | ||||||
1378 | } | ||||||
1379 | |||||||
1380 | /* Try this insn with each REG_EQUAL note it links back to. */ | ||||||
1381 | FOR_EACH_LOG_LINK (links, insn)for ((links) = (uid_log_links[insn_uid_check (insn)]); (links ); (links) = (links)->next) | ||||||
1382 | { | ||||||
1383 | rtx set, note; | ||||||
1384 | rtx_insn *temp = links->insn; | ||||||
1385 | if ((set = single_set (temp)) != 0 | ||||||
1386 | && (note = find_reg_equal_equiv_note (temp)) != 0 | ||||||
1387 | && (note = XEXP (note, 0)(((note)->u.fld[0]).rt_rtx), GET_CODE (note)((enum rtx_code) (note)->code)) != EXPR_LIST | ||||||
1388 | && ! side_effects_p (SET_SRC (set)(((set)->u.fld[1]).rt_rtx)) | ||||||
1389 | /* Avoid using a register that may already been marked | ||||||
1390 | dead by an earlier instruction. */ | ||||||
1391 | && ! unmentioned_reg_p (note, SET_SRC (set)(((set)->u.fld[1]).rt_rtx)) | ||||||
1392 | && (GET_MODE (note)((machine_mode) (note)->mode) == VOIDmode((void) 0, E_VOIDmode) | ||||||
1393 | ? SCALAR_INT_MODE_P (GET_MODE (SET_DEST (set)))(((enum mode_class) mode_class[((machine_mode) ((((set)->u .fld[0]).rt_rtx))->mode)]) == MODE_INT || ((enum mode_class ) mode_class[((machine_mode) ((((set)->u.fld[0]).rt_rtx))-> mode)]) == MODE_PARTIAL_INT) | ||||||
1394 | : (GET_MODE (SET_DEST (set))((machine_mode) ((((set)->u.fld[0]).rt_rtx))->mode) == GET_MODE (note)((machine_mode) (note)->mode) | ||||||
1395 | && (GET_CODE (SET_DEST (set))((enum rtx_code) ((((set)->u.fld[0]).rt_rtx))->code) != ZERO_EXTRACT | ||||||
1396 | || (GET_MODE (XEXP (SET_DEST (set), 0))((machine_mode) (((((((set)->u.fld[0]).rt_rtx))->u.fld[ 0]).rt_rtx))->mode) | ||||||
1397 | == GET_MODE (note)((machine_mode) (note)->mode)))))) | ||||||
1398 | { | ||||||
1399 | /* Temporarily replace the set's source with the | ||||||
1400 | contents of the REG_EQUAL note. The insn will | ||||||
1401 | be deleted or recognized by try_combine. */ | ||||||
1402 | rtx orig_src = SET_SRC (set)(((set)->u.fld[1]).rt_rtx); | ||||||
1403 | rtx orig_dest = SET_DEST (set)(((set)->u.fld[0]).rt_rtx); | ||||||
1404 | if (GET_CODE (SET_DEST (set))((enum rtx_code) ((((set)->u.fld[0]).rt_rtx))->code) == ZERO_EXTRACT) | ||||||
1405 | SET_DEST (set)(((set)->u.fld[0]).rt_rtx) = XEXP (SET_DEST (set), 0)((((((set)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx); | ||||||
1406 | SET_SRC (set)(((set)->u.fld[1]).rt_rtx) = note; | ||||||
1407 | i2mod = temp; | ||||||
1408 | i2mod_old_rhs = copy_rtx (orig_src); | ||||||
1409 | i2mod_new_rhs = copy_rtx (note); | ||||||
1410 | next = try_combine (insn, i2mod, NULLnullptr, NULLnullptr, | ||||||
1411 | &new_direct_jump_p, | ||||||
1412 | last_combined_insn); | ||||||
1413 | i2mod = NULLnullptr; | ||||||
1414 | if (next) | ||||||
1415 | { | ||||||
1416 | statistics_counter_event (cfun(cfun + 0), "insn-with-note combine", 1); | ||||||
1417 | goto retry; | ||||||
1418 | } | ||||||
1419 | SET_SRC (set)(((set)->u.fld[1]).rt_rtx) = orig_src; | ||||||
1420 | SET_DEST (set)(((set)->u.fld[0]).rt_rtx) = orig_dest; | ||||||
1421 | } | ||||||
1422 | } | ||||||
1423 | |||||||
1424 | if (!NOTE_P (insn)(((enum rtx_code) (insn)->code) == NOTE)) | ||||||
1425 | record_dead_and_set_regs (insn); | ||||||
1426 | |||||||
1427 | retry: | ||||||
1428 | ; | ||||||
1429 | } | ||||||
1430 | } | ||||||
1431 | |||||||
1432 | default_rtl_profile (); | ||||||
1433 | clear_bb_flags (); | ||||||
1434 | new_direct_jump_p |= purge_all_dead_edges (); | ||||||
1435 | new_direct_jump_p |= delete_noop_moves (); | ||||||
1436 | |||||||
1437 | /* Clean up. */ | ||||||
1438 | obstack_free (&insn_link_obstack, NULL)__extension__ ({ struct obstack *__o = (&insn_link_obstack ); void *__obj = (void *) (nullptr); if (__obj > (void *) __o ->chunk && __obj < (void *) __o->chunk_limit ) __o->next_free = __o->object_base = (char *) __obj; else _obstack_free (__o, __obj); }); | ||||||
1439 | free (uid_log_links); | ||||||
1440 | free (uid_insn_cost); | ||||||
1441 | reg_stat.release (); | ||||||
1442 | |||||||
1443 | { | ||||||
1444 | struct undo *undo, *next; | ||||||
1445 | for (undo = undobuf.frees; undo; undo = next) | ||||||
1446 | { | ||||||
1447 | next = undo->next; | ||||||
1448 | free (undo); | ||||||
1449 | } | ||||||
1450 | undobuf.frees = 0; | ||||||
1451 | } | ||||||
1452 | |||||||
1453 | total_attempts += combine_attempts; | ||||||
1454 | total_merges += combine_merges; | ||||||
1455 | total_extras += combine_extras; | ||||||
1456 | total_successes += combine_successes; | ||||||
1457 | |||||||
1458 | nonzero_sign_valid = 0; | ||||||
1459 | rtl_hooks = general_rtl_hooks; | ||||||
1460 | |||||||
1461 | /* Make recognizer allow volatile MEMs again. */ | ||||||
1462 | init_recog (); | ||||||
1463 | |||||||
1464 | return new_direct_jump_p; | ||||||
1465 | } | ||||||
1466 | |||||||
1467 | /* Wipe the last_xxx fields of reg_stat in preparation for another pass. */ | ||||||
1468 | |||||||
1469 | static void | ||||||
1470 | init_reg_last (void) | ||||||
1471 | { | ||||||
1472 | unsigned int i; | ||||||
1473 | reg_stat_type *p; | ||||||
1474 | |||||||
1475 | FOR_EACH_VEC_ELT (reg_stat, i, p)for (i = 0; (reg_stat).iterate ((i), &(p)); ++(i)) | ||||||
1476 | memset (p, 0, offsetof (reg_stat_type, sign_bit_copies)__builtin_offsetof(reg_stat_type, sign_bit_copies)); | ||||||
1477 | } | ||||||
1478 | |||||||
1479 | /* Set up any promoted values for incoming argument registers. */ | ||||||
1480 | |||||||
1481 | static void | ||||||
1482 | setup_incoming_promotions (rtx_insn *first) | ||||||
1483 | { | ||||||
1484 | tree arg; | ||||||
1485 | bool strictly_local = false; | ||||||
1486 | |||||||
1487 | for (arg = DECL_ARGUMENTS (current_function_decl)((tree_check ((current_function_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1487, __FUNCTION__, (FUNCTION_DECL)))->function_decl.arguments ); arg; | ||||||
1488 | arg = DECL_CHAIN (arg)(((contains_struct_check (((contains_struct_check ((arg), (TS_DECL_MINIMAL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1488, __FUNCTION__))), (TS_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1488, __FUNCTION__))->common.chain))) | ||||||
1489 | { | ||||||
1490 | rtx x, reg = DECL_INCOMING_RTL (arg)((tree_check ((arg), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1490, __FUNCTION__, (PARM_DECL)))->parm_decl.incoming_rtl ); | ||||||
1491 | int uns1, uns3; | ||||||
1492 | machine_mode mode1, mode2, mode3, mode4; | ||||||
1493 | |||||||
1494 | /* Only continue if the incoming argument is in a register. */ | ||||||
1495 | if (!REG_P (reg)(((enum rtx_code) (reg)->code) == REG)) | ||||||
1496 | continue; | ||||||
1497 | |||||||
1498 | /* Determine, if possible, whether all call sites of the current | ||||||
1499 | function lie within the current compilation unit. (This does | ||||||
1500 | take into account the exporting of a function via taking its | ||||||
1501 | address, and so forth.) */ | ||||||
1502 | strictly_local | ||||||
1503 | = cgraph_node::local_info_node (current_function_decl)->local; | ||||||
1504 | |||||||
1505 | /* The mode and signedness of the argument before any promotions happen | ||||||
1506 | (equal to the mode of the pseudo holding it at that stage). */ | ||||||
1507 | mode1 = TYPE_MODE (TREE_TYPE (arg))((((enum tree_code) ((tree_class_check ((((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1507, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1507, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1507, __FUNCTION__))->typed.type)) : (((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1507, __FUNCTION__))->typed.type))->type_common.mode); | ||||||
1508 | uns1 = TYPE_UNSIGNED (TREE_TYPE (arg))((tree_class_check ((((contains_struct_check ((arg), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1508, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1508, __FUNCTION__))->base.u.bits.unsigned_flag); | ||||||
1509 | |||||||
1510 | /* The mode and signedness of the argument after any source language and | ||||||
1511 | TARGET_PROMOTE_PROTOTYPES-driven promotions. */ | ||||||
1512 | mode2 = TYPE_MODE (DECL_ARG_TYPE (arg))((((enum tree_code) ((tree_class_check ((((tree_check ((arg), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1512, __FUNCTION__, (PARM_DECL)))->decl_common.initial)) , (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1512, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (((tree_check ((arg), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1512, __FUNCTION__, (PARM_DECL)))->decl_common.initial)) : (((tree_check ((arg), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1512, __FUNCTION__, (PARM_DECL)))->decl_common.initial)) ->type_common.mode); | ||||||
1513 | uns3 = TYPE_UNSIGNED (DECL_ARG_TYPE (arg))((tree_class_check ((((tree_check ((arg), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1513, __FUNCTION__, (PARM_DECL)))->decl_common.initial)) , (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1513, __FUNCTION__))->base.u.bits.unsigned_flag); | ||||||
1514 | |||||||
1515 | /* The mode and signedness of the argument as it is actually passed, | ||||||
1516 | see assign_parm_setup_reg in function.cc. */ | ||||||
1517 | mode3 = promote_function_mode (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1517, __FUNCTION__))->typed.type), mode1, &uns3, | ||||||
1518 | TREE_TYPE (cfun->decl)((contains_struct_check (((cfun + 0)->decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1518, __FUNCTION__))->typed.type), 0); | ||||||
1519 | |||||||
1520 | /* The mode of the register in which the argument is being passed. */ | ||||||
1521 | mode4 = GET_MODE (reg)((machine_mode) (reg)->mode); | ||||||
1522 | |||||||
1523 | /* Eliminate sign extensions in the callee when: | ||||||
1524 | (a) A mode promotion has occurred; */ | ||||||
1525 | if (mode1 == mode3) | ||||||
1526 | continue; | ||||||
1527 | /* (b) The mode of the register is the same as the mode of | ||||||
1528 | the argument as it is passed; */ | ||||||
1529 | if (mode3 != mode4) | ||||||
1530 | continue; | ||||||
1531 | /* (c) There's no language level extension; */ | ||||||
1532 | if (mode1 == mode2) | ||||||
1533 | ; | ||||||
1534 | /* (c.1) All callers are from the current compilation unit. If that's | ||||||
1535 | the case we don't have to rely on an ABI, we only have to know | ||||||
1536 | what we're generating right now, and we know that we will do the | ||||||
1537 | mode1 to mode2 promotion with the given sign. */ | ||||||
1538 | else if (!strictly_local) | ||||||
1539 | continue; | ||||||
1540 | /* (c.2) The combination of the two promotions is useful. This is | ||||||
1541 | true when the signs match, or if the first promotion is unsigned. | ||||||
1542 | In the later case, (sign_extend (zero_extend x)) is the same as | ||||||
1543 | (zero_extend (zero_extend x)), so make sure to force UNS3 true. */ | ||||||
1544 | else if (uns1) | ||||||
1545 | uns3 = true; | ||||||
1546 | else if (uns3) | ||||||
1547 | continue; | ||||||
1548 | |||||||
1549 | /* Record that the value was promoted from mode1 to mode3, | ||||||
1550 | so that any sign extension at the head of the current | ||||||
1551 | function may be eliminated. */ | ||||||
1552 | x = gen_rtx_CLOBBER (mode1, const0_rtx)gen_rtx_fmt_e_stat ((CLOBBER), ((mode1)), (((const_int_rtx[64 ]))) ); | ||||||
1553 | x = gen_rtx_fmt_e ((uns3 ? ZERO_EXTEND : SIGN_EXTEND), mode3, x)gen_rtx_fmt_e_stat (((uns3 ? ZERO_EXTEND : SIGN_EXTEND)), (mode3 ), (x) ); | ||||||
1554 | record_value_for_reg (reg, first, x); | ||||||
1555 | } | ||||||
1556 | } | ||||||
1557 | |||||||
1558 | /* If MODE has a precision lower than PREC and SRC is a non-negative constant | ||||||
1559 | that would appear negative in MODE, sign-extend SRC for use in nonzero_bits | ||||||
1560 | because some machines (maybe most) will actually do the sign-extension and | ||||||
1561 | this is the conservative approach. | ||||||
1562 | |||||||
1563 | ??? For 2.5, try to tighten up the MD files in this regard instead of this | ||||||
1564 | kludge. */ | ||||||
1565 | |||||||
1566 | static rtx | ||||||
1567 | sign_extend_short_imm (rtx src, machine_mode mode, unsigned int prec) | ||||||
1568 | { | ||||||
1569 | scalar_int_mode int_mode; | ||||||
1570 | if (CONST_INT_P (src)(((enum rtx_code) (src)->code) == CONST_INT) | ||||||
1571 | && is_a <scalar_int_mode> (mode, &int_mode) | ||||||
1572 | && GET_MODE_PRECISION (int_mode) < prec | ||||||
1573 | && INTVAL (src)((src)->u.hwint[0]) > 0 | ||||||
1574 | && val_signbit_known_set_p (int_mode, INTVAL (src)((src)->u.hwint[0]))) | ||||||
1575 | src = GEN_INT (INTVAL (src) | ~GET_MODE_MASK (int_mode))gen_rtx_CONST_INT (((void) 0, E_VOIDmode), (((src)->u.hwint [0]) | ~mode_mask_array[int_mode])); | ||||||
1576 | |||||||
1577 | return src; | ||||||
1578 | } | ||||||
1579 | |||||||
1580 | /* Update RSP for pseudo-register X from INSN's REG_EQUAL note (if one exists) | ||||||
1581 | and SET. */ | ||||||
1582 | |||||||
1583 | static void | ||||||
1584 | update_rsp_from_reg_equal (reg_stat_type *rsp, rtx_insn *insn, const_rtx set, | ||||||
1585 | rtx x) | ||||||
1586 | { | ||||||
1587 | rtx reg_equal_note = insn ? find_reg_equal_equiv_note (insn) : NULL_RTX(rtx) 0; | ||||||
1588 | unsigned HOST_WIDE_INTlong bits = 0; | ||||||
1589 | rtx reg_equal = NULLnullptr, src = SET_SRC (set)(((set)->u.fld[1]).rt_rtx); | ||||||
1590 | unsigned int num = 0; | ||||||
1591 | |||||||
1592 | if (reg_equal_note) | ||||||
1593 | reg_equal = XEXP (reg_equal_note, 0)(((reg_equal_note)->u.fld[0]).rt_rtx); | ||||||
1594 | |||||||
1595 | if (SHORT_IMMEDIATES_SIGN_EXTEND0) | ||||||
1596 | { | ||||||
1597 | src = sign_extend_short_imm (src, GET_MODE (x)((machine_mode) (x)->mode), BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))); | ||||||
1598 | if (reg_equal) | ||||||
1599 | reg_equal = sign_extend_short_imm (reg_equal, GET_MODE (x)((machine_mode) (x)->mode), BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4))); | ||||||
1600 | } | ||||||
1601 | |||||||
1602 | /* Don't call nonzero_bits if it cannot change anything. */ | ||||||
1603 | if (rsp->nonzero_bits != HOST_WIDE_INT_M1U-1UL) | ||||||
1604 | { | ||||||
1605 | machine_mode mode = GET_MODE (x)((machine_mode) (x)->mode); | ||||||
1606 | if (GET_MODE_CLASS (mode)((enum mode_class) mode_class[mode]) == MODE_INT | ||||||
1607 | && HWI_COMPUTABLE_MODE_P (mode)) | ||||||
1608 | mode = nonzero_bits_mode; | ||||||
1609 | bits = nonzero_bits (src, mode); | ||||||
1610 | if (reg_equal && bits) | ||||||
1611 | bits &= nonzero_bits (reg_equal, mode); | ||||||
1612 | rsp->nonzero_bits |= bits; | ||||||
1613 | } | ||||||
1614 | |||||||
1615 | /* Don't call num_sign_bit_copies if it cannot change anything. */ | ||||||
1616 | if (rsp->sign_bit_copies != 1) | ||||||
1617 | { | ||||||
1618 | num = num_sign_bit_copies (SET_SRC (set)(((set)->u.fld[1]).rt_rtx), GET_MODE (x)((machine_mode) (x)->mode)); | ||||||
1619 | if (reg_equal && maybe_ne (num, GET_MODE_PRECISION (GET_MODE (x)((machine_mode) (x)->mode)))) | ||||||
1620 | { | ||||||
1621 | unsigned int numeq = num_sign_bit_copies (reg_equal, GET_MODE (x)((machine_mode) (x)->mode)); | ||||||
1622 | if (num == 0 || numeq > num) | ||||||
1623 | num = numeq; | ||||||
1624 | } | ||||||
1625 | if (rsp->sign_bit_copies == 0 || num < rsp->sign_bit_copies) | ||||||
1626 | rsp->sign_bit_copies = num; | ||||||
1627 | } | ||||||
1628 | } | ||||||
1629 | |||||||
1630 | /* Called via note_stores. If X is a pseudo that is narrower than | ||||||
1631 | HOST_BITS_PER_WIDE_INT and is being set, record what bits are known zero. | ||||||
1632 | |||||||
1633 | If we are setting only a portion of X and we can't figure out what | ||||||
1634 | portion, assume all bits will be used since we don't know what will | ||||||
1635 | be happening. | ||||||
1636 | |||||||
1637 | Similarly, set how many bits of X are known to be copies of the sign bit | ||||||
1638 | at all locations in the function. This is the smallest number implied | ||||||
1639 | by any set of X. */ | ||||||
1640 | |||||||
1641 | static void | ||||||
1642 | set_nonzero_bits_and_sign_copies (rtx x, const_rtx set, void *data) | ||||||
1643 | { | ||||||
1644 | rtx_insn *insn = (rtx_insn *) data; | ||||||
1645 | scalar_int_mode mode; | ||||||
1646 | |||||||
1647 | if (REG_P (x)(((enum rtx_code) (x)->code) == REG) | ||||||
1648 | && REGNO (x)(rhs_regno(x)) >= FIRST_PSEUDO_REGISTER76 | ||||||
1649 | /* If this register is undefined at the start of the file, we can't | ||||||
1650 | say what its contents were. */ | ||||||
1651 | && ! REGNO_REG_SET_Pbitmap_bit_p ((&(df_lr_get_bb_info (((((cfun + 0))->cfg ->x_entry_block_ptr)->next_bb)->index))->in), (rhs_regno (x))) | ||||||
1652 | (DF_LR_IN (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb), REGNO (x))bitmap_bit_p ((&(df_lr_get_bb_info (((((cfun + 0))->cfg ->x_entry_block_ptr)->next_bb)->index))->in), (rhs_regno (x))) | ||||||
1653 | && is_a <scalar_int_mode> (GET_MODE (x)((machine_mode) (x)->mode), &mode) | ||||||
1654 | && HWI_COMPUTABLE_MODE_P (mode)) | ||||||
1655 | { | ||||||
1656 | reg_stat_type *rsp = ®_stat[REGNO (x)(rhs_regno(x))]; | ||||||
1657 | |||||||
1658 | if (set == 0 || GET_CODE (set)((enum rtx_code) (set)->code) == CLOBBER) | ||||||
1659 | { | ||||||
1660 | rsp->nonzero_bits = GET_MODE_MASK (mode)mode_mask_array[mode]; | ||||||
1661 | rsp->sign_bit_copies = 1; | ||||||
1662 | return; | ||||||
1663 | } | ||||||
1664 | |||||||
1665 | /* If this register is being initialized using itself, and the | ||||||
1666 | register is uninitialized in this basic block, and there are | ||||||
1667 | no LOG_LINKS which set the register, then part of the | ||||||
1668 | register is uninitialized. In that case we can't assume | ||||||
1669 | anything about the number of nonzero bits. | ||||||
1670 | |||||||
1671 | ??? We could do better if we checked this in | ||||||
1672 | reg_{nonzero_bits,num_sign_bit_copies}_for_combine. Then we | ||||||
1673 | could avoid making assumptions about the insn which initially | ||||||
1674 | sets the register, while still using the information in other | ||||||
1675 | insns. We would have to be careful to check every insn | ||||||
1676 | involved in the combination. */ | ||||||
1677 | |||||||
1678 | if (insn | ||||||
1679 | && reg_referenced_p (x, PATTERN (insn)) | ||||||
1680 | && !REGNO_REG_SET_P (DF_LR_IN (BLOCK_FOR_INSN (insn)),bitmap_bit_p ((&(df_lr_get_bb_info ((BLOCK_FOR_INSN (insn ))->index))->in), (rhs_regno(x))) | ||||||
1681 | REGNO (x))bitmap_bit_p ((&(df_lr_get_bb_info ((BLOCK_FOR_INSN (insn ))->index))->in), (rhs_regno(x)))) | ||||||
1682 | { | ||||||
1683 | struct insn_link *link; | ||||||
1684 | |||||||
1685 | FOR_EACH_LOG_LINK (link, insn)for ((link) = (uid_log_links[insn_uid_check (insn)]); (link); (link) = (link)->next) | ||||||
1686 | if (dead_or_set_p (link->insn, x)) | ||||||
1687 | break; | ||||||
1688 | if (!link) | ||||||
1689 | { | ||||||
1690 | rsp->nonzero_bits = GET_MODE_MASK (mode)mode_mask_array[mode]; | ||||||
1691 | rsp->sign_bit_copies = 1; | ||||||
1692 | return; | ||||||
1693 | } | ||||||
1694 | } | ||||||
1695 | |||||||
1696 | /* If this is a complex assignment, see if we can convert it into a | ||||||
1697 | simple assignment. */ | ||||||
1698 | set = expand_field_assignment (set); | ||||||
1699 | |||||||
1700 | /* If this is a simple assignment, or we have a paradoxical SUBREG, | ||||||
1701 | set what we know about X. */ | ||||||
1702 | |||||||
1703 | if (SET_DEST (set)(((set)->u.fld[0]).rt_rtx) == x | ||||||
1704 | || (paradoxical_subreg_p (SET_DEST (set)(((set)->u.fld[0]).rt_rtx)) | ||||||
1705 | && SUBREG_REG (SET_DEST (set))((((((set)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx) == x)) | ||||||
1706 | update_rsp_from_reg_equal (rsp, insn, set, x); | ||||||
1707 | else | ||||||
1708 | { | ||||||
1709 | rsp->nonzero_bits = GET_MODE_MASK (mode)mode_mask_array[mode]; | ||||||
1710 | rsp->sign_bit_copies = 1; | ||||||
1711 | } | ||||||
1712 | } | ||||||
1713 | } | ||||||
1714 | |||||||
1715 | /* See if INSN can be combined into I3. PRED, PRED2, SUCC and SUCC2 are | ||||||
1716 | optionally insns that were previously combined into I3 or that will be | ||||||
1717 | combined into the merger of INSN and I3. The order is PRED, PRED2, | ||||||
1718 | INSN, SUCC, SUCC2, I3. | ||||||
1719 | |||||||
1720 | Return 0 if the combination is not allowed for any reason. | ||||||
1721 | |||||||
1722 | If the combination is allowed, *PDEST will be set to the single | ||||||
1723 | destination of INSN and *PSRC to the single source, and this function | ||||||
1724 | will return 1. */ | ||||||
1725 | |||||||
1726 | static int | ||||||
1727 | can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED__attribute__ ((__unused__)), | ||||||
1728 | rtx_insn *pred2 ATTRIBUTE_UNUSED__attribute__ ((__unused__)), rtx_insn *succ, rtx_insn *succ2, | ||||||
1729 | rtx *pdest, rtx *psrc) | ||||||
1730 | { | ||||||
1731 | int i; | ||||||
1732 | const_rtx set = 0; | ||||||
1733 | rtx src, dest; | ||||||
1734 | rtx_insn *p; | ||||||
1735 | rtx link; | ||||||
1736 | bool all_adjacent = true; | ||||||
1737 | int (*is_volatile_p) (const_rtx); | ||||||
1738 | |||||||
1739 | if (succ) | ||||||
1740 | { | ||||||
1741 | if (succ2) | ||||||
1742 | { | ||||||
1743 | if (next_active_insn (succ2) != i3) | ||||||
1744 | all_adjacent = false; | ||||||
1745 | if (next_active_insn (succ) != succ2) | ||||||
1746 | all_adjacent = false; | ||||||
1747 | } | ||||||
1748 | else if (next_active_insn (succ) != i3) | ||||||
1749 | all_adjacent = false; | ||||||
1750 | if (next_active_insn (insn) != succ) | ||||||
1751 | all_adjacent = false; | ||||||
1752 | } | ||||||
1753 | else if (next_active_insn (insn) != i3) | ||||||
1754 | all_adjacent = false; | ||||||
1755 | |||||||
1756 | /* Can combine only if previous insn is a SET of a REG or a SUBREG, | ||||||
1757 | or a PARALLEL consisting of such a SET and CLOBBERs. | ||||||
1758 | |||||||
1759 | If INSN has CLOBBER parallel parts, ignore them for our processing. | ||||||
1760 | By definition, these happen during the execution of the insn. When it | ||||||
1761 | is merged with another insn, all bets are off. If they are, in fact, | ||||||
1762 | needed and aren't also supplied in I3, they may be added by | ||||||
1763 | recog_for_combine. Otherwise, it won't match. | ||||||
1764 | |||||||
1765 | We can also ignore a SET whose SET_DEST is mentioned in a REG_UNUSED | ||||||
1766 | note. | ||||||
1767 | |||||||
1768 | Get the source and destination of INSN. If more than one, can't | ||||||
1769 | combine. */ | ||||||
1770 | |||||||
1771 | if (GET_CODE (PATTERN (insn))((enum rtx_code) (PATTERN (insn))->code) == SET) | ||||||
1772 | set = PATTERN (insn); | ||||||
1773 | else if (GET_CODE (PATTERN (insn))((enum rtx_code) (PATTERN (insn))->code) == PARALLEL | ||||||
1774 | && GET_CODE (XVECEXP (PATTERN (insn), 0, 0))((enum rtx_code) ((((((PATTERN (insn))->u.fld[0]).rt_rtvec ))->elem[0]))->code) == SET) | ||||||
1775 | { | ||||||
1776 | for (i = 0; i < XVECLEN (PATTERN (insn), 0)(((((PATTERN (insn))->u.fld[0]).rt_rtvec))->num_elem); i++) | ||||||
1777 | { | ||||||
1778 | rtx elt = XVECEXP (PATTERN (insn), 0, i)(((((PATTERN (insn))->u.fld[0]).rt_rtvec))->elem[i]); | ||||||
1779 | |||||||
1780 | switch (GET_CODE (elt)((enum rtx_code) (elt)->code)) | ||||||
1781 | { | ||||||
1782 | /* This is important to combine floating point insns | ||||||
1783 | for the SH4 port. */ | ||||||
1784 | case USE: | ||||||
1785 | /* Combining an isolated USE doesn't make sense. | ||||||
1786 | We depend here on combinable_i3pat to reject them. */ | ||||||
1787 | /* The code below this loop only verifies that the inputs of | ||||||
1788 | the SET in INSN do not change. We call reg_set_between_p | ||||||
1789 | to verify that the REG in the USE does not change between | ||||||
1790 | I3 and INSN. | ||||||
1791 | If the USE in INSN was for a pseudo register, the matching | ||||||
1792 | insn pattern will likely match any register; combining this | ||||||
1793 | with any other USE would only be safe if we knew that the | ||||||
1794 | used registers have identical values, or if there was | ||||||
1795 | something to tell them apart, e.g. different modes. For | ||||||
1796 | now, we forgo such complicated tests and simply disallow | ||||||
1797 | combining of USES of pseudo registers with any other USE. */ | ||||||
1798 | if (REG_P (XEXP (elt, 0))(((enum rtx_code) ((((elt)->u.fld[0]).rt_rtx))->code) == REG) | ||||||
1799 | && GET_CODE (PATTERN (i3))((enum rtx_code) (PATTERN (i3))->code) == PARALLEL) | ||||||
1800 | { | ||||||
1801 | rtx i3pat = PATTERN (i3); | ||||||
1802 | int i = XVECLEN (i3pat, 0)(((((i3pat)->u.fld[0]).rt_rtvec))->num_elem) - 1; | ||||||
1803 | unsigned int regno = REGNO (XEXP (elt, 0))(rhs_regno((((elt)->u.fld[0]).rt_rtx))); | ||||||
1804 | |||||||
1805 | do | ||||||
1806 | { | ||||||
1807 | rtx i3elt = XVECEXP (i3pat, 0, i)(((((i3pat)->u.fld[0]).rt_rtvec))->elem[i]); | ||||||
1808 | |||||||
1809 | if (GET_CODE (i3elt)((enum rtx_code) (i3elt)->code) == USE | ||||||
1810 | && REG_P (XEXP (i3elt, 0))(((enum rtx_code) ((((i3elt)->u.fld[0]).rt_rtx))->code) == REG) | ||||||
1811 | && (REGNO (XEXP (i3elt, 0))(rhs_regno((((i3elt)->u.fld[0]).rt_rtx))) == regno | ||||||
1812 | ? reg_set_between_p (XEXP (elt, 0)(((elt)->u.fld[0]).rt_rtx), | ||||||
1813 | PREV_INSN (insn), i3) | ||||||
1814 | : regno >= FIRST_PSEUDO_REGISTER76)) | ||||||
1815 | return 0; | ||||||
1816 | } | ||||||
1817 | while (--i >= 0); | ||||||
1818 | } | ||||||
1819 | break; | ||||||
1820 | |||||||
1821 | /* We can ignore CLOBBERs. */ | ||||||
1822 | case CLOBBER: | ||||||
1823 | break; | ||||||
1824 | |||||||
1825 | case SET: | ||||||
1826 | /* Ignore SETs whose result isn't used but not those that | ||||||
1827 | have side-effects. */ | ||||||
1828 | if (find_reg_note (insn, REG_UNUSED, SET_DEST (elt)(((elt)->u.fld[0]).rt_rtx)) | ||||||
1829 | && insn_nothrow_p (insn) | ||||||
1830 | && !side_effects_p (elt)) | ||||||
1831 | break; | ||||||
1832 | |||||||
1833 | /* If we have already found a SET, this is a second one and | ||||||
1834 | so we cannot combine with this insn. */ | ||||||
1835 | if (set) | ||||||
1836 | return 0; | ||||||
1837 | |||||||
1838 | set = elt; | ||||||
1839 | break; | ||||||
1840 | |||||||
1841 | default: | ||||||
1842 | /* Anything else means we can't combine. */ | ||||||
1843 | return 0; | ||||||
1844 | } | ||||||
1845 | } | ||||||
1846 | |||||||
1847 | if (set == 0 | ||||||
1848 | /* If SET_SRC is an ASM_OPERANDS we can't throw away these CLOBBERs, | ||||||
1849 | so don't do anything with it. */ | ||||||
1850 | || GET_CODE (SET_SRC (set))((enum rtx_code) ((((set)->u.fld[1]).rt_rtx))->code) == ASM_OPERANDS) | ||||||
1851 | return 0; | ||||||
1852 | } | ||||||
1853 | else | ||||||
1854 | return 0; | ||||||
1855 | |||||||
1856 | if (set == 0) | ||||||
1857 | return 0; | ||||||
1858 | |||||||
1859 | /* The simplification in expand_field_assignment may call back to | ||||||
1860 | get_last_value, so set safe guard here. */ | ||||||
1861 | subst_low_luid = DF_INSN_LUID (insn)((((df->insns[(INSN_UID (insn))]))->luid)); | ||||||
1862 | |||||||
1863 | set = expand_field_assignment (set); | ||||||
1864 | src = SET_SRC (set)(((set)->u.fld[1]).rt_rtx), dest = SET_DEST (set)(((set)->u.fld[0]).rt_rtx); | ||||||
1865 | |||||||
1866 | /* Do not eliminate user-specified register if it is in an | ||||||
1867 | asm input because we may break the register asm usage defined | ||||||
1868 | in GCC manual if allow to do so. | ||||||
1869 | Be aware that this may cover more cases than we expect but this | ||||||
1870 | should be harmless. */ | ||||||
1871 | if (REG_P (dest)(((enum rtx_code) (dest)->code) == REG) && REG_USERVAR_P (dest)(__extension__ ({ __typeof ((dest)) const _rtx = ((dest)); if (((enum rtx_code) (_rtx)->code) != REG) rtl_check_failed_flag ("REG_USERVAR_P", _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1871, __FUNCTION__); _rtx; })->volatil) && HARD_REGISTER_P (dest)((((rhs_regno(dest))) < 76)) | ||||||
1872 | && extract_asm_operands (PATTERN (i3))) | ||||||
1873 | return 0; | ||||||
1874 | |||||||
1875 | /* Don't eliminate a store in the stack pointer. */ | ||||||
1876 | if (dest == stack_pointer_rtx((this_target_rtl->x_global_rtl)[GR_STACK_POINTER]) | ||||||
1877 | /* Don't combine with an insn that sets a register to itself if it has | ||||||
1878 | a REG_EQUAL note. This may be part of a LIBCALL sequence. */ | ||||||
1879 | || (rtx_equal_p (src, dest) && find_reg_note (insn, REG_EQUAL, NULL_RTX(rtx) 0)) | ||||||
1880 | /* Can't merge an ASM_OPERANDS. */ | ||||||
1881 | || GET_CODE (src)((enum rtx_code) (src)->code) == ASM_OPERANDS | ||||||
1882 | /* Can't merge a function call. */ | ||||||
1883 | || GET_CODE (src)((enum rtx_code) (src)->code) == CALL | ||||||
1884 | /* Don't eliminate a function call argument. */ | ||||||
1885 | || (CALL_P (i3)(((enum rtx_code) (i3)->code) == CALL_INSN) | ||||||
1886 | && (find_reg_fusage (i3, USE, dest) | ||||||
1887 | || (REG_P (dest)(((enum rtx_code) (dest)->code) == REG) | ||||||
1888 | && REGNO (dest)(rhs_regno(dest)) < FIRST_PSEUDO_REGISTER76 | ||||||
1889 | && global_regs[REGNO (dest)(rhs_regno(dest))]))) | ||||||
1890 | /* Don't substitute into an incremented register. */ | ||||||
1891 | || FIND_REG_INC_NOTE (i3, dest)0 | ||||||
1892 | || (succ && FIND_REG_INC_NOTE (succ, dest)0) | ||||||
1893 | || (succ2 && FIND_REG_INC_NOTE (succ2, dest)0) | ||||||
1894 | /* Don't substitute into a non-local goto, this confuses CFG. */ | ||||||
1895 | || (JUMP_P (i3)(((enum rtx_code) (i3)->code) == JUMP_INSN) && find_reg_note (i3, REG_NON_LOCAL_GOTO, NULL_RTX(rtx) 0)) | ||||||
1896 | /* Make sure that DEST is not used after INSN but before SUCC, or | ||||||
1897 | after SUCC and before SUCC2, or after SUCC2 but before I3. */ | ||||||
1898 | || (!all_adjacent | ||||||
1899 | && ((succ2 | ||||||
1900 | && (reg_used_between_p (dest, succ2, i3) | ||||||
1901 | || reg_used_between_p (dest, succ, succ2))) | ||||||
1902 | || (!succ2 && succ && reg_used_between_p (dest, succ, i3)) | ||||||
1903 | || (!succ2 && !succ && reg_used_between_p (dest, insn, i3)) | ||||||
1904 | || (succ | ||||||
1905 | /* SUCC and SUCC2 can be split halves from a PARALLEL; in | ||||||
1906 | that case SUCC is not in the insn stream, so use SUCC2 | ||||||
1907 | instead for this test. */ | ||||||
1908 | && reg_used_between_p (dest, insn, | ||||||
1909 | succ2 | ||||||
1910 | && INSN_UID (succ) == INSN_UID (succ2) | ||||||
1911 | ? succ2 : succ)))) | ||||||
1912 | /* Make sure that the value that is to be substituted for the register | ||||||
1913 | does not use any registers whose values alter in between. However, | ||||||
1914 | If the insns are adjacent, a use can't cross a set even though we | ||||||
1915 | think it might (this can happen for a sequence of insns each setting | ||||||
1916 | the same destination; last_set of that register might point to | ||||||
1917 | a NOTE). If INSN has a REG_EQUIV note, the register is always | ||||||
1918 | equivalent to the memory so the substitution is valid even if there | ||||||
1919 | are intervening stores. Also, don't move a volatile asm or | ||||||
1920 | UNSPEC_VOLATILE across any other insns. */ | ||||||
1921 | || (! all_adjacent | ||||||
1922 | && (((!MEM_P (src)(((enum rtx_code) (src)->code) == MEM) | ||||||
1923 | || ! find_reg_note (insn, REG_EQUIV, src)) | ||||||
1924 | && modified_between_p (src, insn, i3)) | ||||||
1925 | || (GET_CODE (src)((enum rtx_code) (src)->code) == ASM_OPERANDS && MEM_VOLATILE_P (src)(__extension__ ({ __typeof ((src)) const _rtx = ((src)); if ( ((enum rtx_code) (_rtx)->code) != MEM && ((enum rtx_code ) (_rtx)->code) != ASM_OPERANDS && ((enum rtx_code ) (_rtx)->code) != ASM_INPUT) rtl_check_failed_flag ("MEM_VOLATILE_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 1925, __FUNCTION__); _rtx; })->volatil)) | ||||||
1926 | || GET_CODE (src)((enum rtx_code) (src)->code) == UNSPEC_VOLATILE)) | ||||||
1927 | /* Don't combine across a CALL_INSN, because that would possibly | ||||||
1928 | change whether the life span of some REGs crosses calls or not, | ||||||
1929 | and it is a pain to update that information. | ||||||
1930 | Exception: if source is a constant, moving it later can't hurt. | ||||||
1931 | Accept that as a special case. */ | ||||||
1932 | || (DF_INSN_LUID (insn)((((df->insns[(INSN_UID (insn))]))->luid)) < last_call_luid && ! CONSTANT_P (src)((rtx_class[(int) (((enum rtx_code) (src)->code))]) == RTX_CONST_OBJ ))) | ||||||
1933 | return 0; | ||||||
1934 | |||||||
1935 | /* DEST must be a REG. */ | ||||||
1936 | if (REG_P (dest)(((enum rtx_code) (dest)->code) == REG)) | ||||||
1937 | { | ||||||
1938 | /* If register alignment is being enforced for multi-word items in all | ||||||
1939 | cases except for parameters, it is possible to have a register copy | ||||||
1940 | insn referencing a hard register that is not allowed to contain the | ||||||
1941 | mode being copied and which would not be valid as an operand of most | ||||||
1942 | insns. Eliminate this problem by not combining with such an insn. | ||||||
1943 | |||||||
1944 | Also, on some machines we don't want to extend the life of a hard | ||||||
1945 | register. */ | ||||||
1946 | |||||||
1947 | if (REG_P (src)(((enum rtx_code) (src)->code) == REG) | ||||||
1948 | && ((REGNO (dest)(rhs_regno(dest)) < FIRST_PSEUDO_REGISTER76 | ||||||
1949 | && !targetm.hard_regno_mode_ok (REGNO (dest)(rhs_regno(dest)), GET_MODE (dest)((machine_mode) (dest)->mode))) | ||||||
1950 | /* Don't extend the life of a hard register unless it is | ||||||
1951 | user variable (if we have few registers) or it can't | ||||||
1952 | fit into the desired register (meaning something special | ||||||
1953 | is going on). | ||||||
1954 | Also avoid substituting a return register into I3, because | ||||||
1955 | reload can't handle a conflict with constraints of other | ||||||
1956 | inputs. */ | ||||||
1957 | || (REGNO (src)(rhs_regno(src)) < FIRST_PSEUDO_REGISTER76 | ||||||
1958 | && !targetm.hard_regno_mode_ok (REGNO (src)(rhs_regno(src)), | ||||||
1959 | GET_MODE (src)((machine_mode) (src)->mode))))) | ||||||
1960 | return 0; | ||||||
1961 | } | ||||||
1962 | else | ||||||
1963 | return 0; | ||||||
1964 | |||||||
1965 | |||||||
1966 | if (GET_CODE (PATTERN (i3))((enum rtx_code) (PATTERN (i3))->code) == PARALLEL) | ||||||
1967 | for (i = XVECLEN (PATTERN (i3), 0)(((((PATTERN (i3))->u.fld[0]).rt_rtvec))->num_elem) - 1; i >= 0; i--) | ||||||
1968 | if (GET_CODE (XVECEXP (PATTERN (i3), 0, i))((enum rtx_code) ((((((PATTERN (i3))->u.fld[0]).rt_rtvec)) ->elem[i]))->code) == CLOBBER) | ||||||
1969 | { | ||||||
1970 | rtx reg = XEXP (XVECEXP (PATTERN (i3), 0, i), 0)((((((((PATTERN (i3))->u.fld[0]).rt_rtvec))->elem[i]))-> u.fld[0]).rt_rtx); | ||||||
1971 | |||||||
1972 | /* If the clobber represents an earlyclobber operand, we must not | ||||||
1973 | substitute an expression containing the clobbered register. | ||||||
1974 | As we do not analyze the constraint strings here, we have to | ||||||
1975 | make the conservative assumption. However, if the register is | ||||||
1976 | a fixed hard reg, the clobber cannot represent any operand; | ||||||
1977 | we leave it up to the machine description to either accept or | ||||||
1978 | reject use-and-clobber patterns. */ | ||||||
1979 | if (!REG_P (reg)(((enum rtx_code) (reg)->code) == REG) | ||||||
1980 | || REGNO (reg)(rhs_regno(reg)) >= FIRST_PSEUDO_REGISTER76 | ||||||
1981 | || !fixed_regs(this_target_hard_regs->x_fixed_regs)[REGNO (reg)(rhs_regno(reg))]) | ||||||
1982 | if (reg_overlap_mentioned_p (reg, src)) | ||||||
1983 | return 0; | ||||||
1984 | } | ||||||
1985 | |||||||
1986 | /* If INSN contains anything volatile, or is an `asm' (whether volatile | ||||||
1987 | or not), reject, unless nothing volatile comes between it and I3 */ | ||||||
1988 | |||||||
1989 | if (GET_CODE (src)((enum rtx_code) (src)->code) == ASM_OPERANDS || volatile_refs_p (src)) | ||||||
1990 | { | ||||||
1991 | /* Make sure neither succ nor succ2 contains a volatile reference. */ | ||||||
1992 | if (succ2 != 0 && volatile_refs_p (PATTERN (succ2))) | ||||||
1993 | return 0; | ||||||
1994 | if (succ != 0 && volatile_refs_p (PATTERN (succ))) | ||||||
1995 | return 0; | ||||||
1996 | /* We'll check insns between INSN and I3 below. */ | ||||||
1997 | } | ||||||
1998 | |||||||
1999 | /* If INSN is an asm, and DEST is a hard register, reject, since it has | ||||||
2000 | to be an explicit register variable, and was chosen for a reason. */ | ||||||
2001 | |||||||
2002 | if (GET_CODE (src)((enum rtx_code) (src)->code) == ASM_OPERANDS | ||||||
2003 | && REG_P (dest)(((enum rtx_code) (dest)->code) == REG) && REGNO (dest)(rhs_regno(dest)) < FIRST_PSEUDO_REGISTER76) | ||||||
2004 | return 0; | ||||||
2005 | |||||||
2006 | /* If INSN contains volatile references (specifically volatile MEMs), | ||||||
2007 | we cannot combine across any other volatile references. | ||||||
2008 | Even if INSN doesn't contain volatile references, any intervening | ||||||
2009 | volatile insn might affect machine state. */ | ||||||
2010 | |||||||
2011 | is_volatile_p = volatile_refs_p (PATTERN (insn)) | ||||||
2012 | ? volatile_refs_p | ||||||
2013 | : volatile_insn_p; | ||||||
2014 | |||||||
2015 | for (p = NEXT_INSN (insn); p != i3; p = NEXT_INSN (p)) | ||||||
2016 | if (INSN_P (p)(((((enum rtx_code) (p)->code) == INSN) || (((enum rtx_code ) (p)->code) == JUMP_INSN) || (((enum rtx_code) (p)->code ) == CALL_INSN)) || (((enum rtx_code) (p)->code) == DEBUG_INSN )) && p != succ && p != succ2 && is_volatile_p (PATTERN (p))) | ||||||
2017 | return 0; | ||||||
2018 | |||||||
2019 | /* If INSN contains an autoincrement or autodecrement, make sure that | ||||||
2020 | register is not used between there and I3, and not already used in | ||||||
2021 | I3 either. Neither must it be used in PRED or SUCC, if they exist. | ||||||
2022 | Also insist that I3 not be a jump if using LRA; if it were one | ||||||
2023 | and the incremented register were spilled, we would lose. | ||||||
2024 | Reload handles this correctly. */ | ||||||
2025 | |||||||
2026 | if (AUTO_INC_DEC0) | ||||||
2027 | for (link = REG_NOTES (insn)(((insn)->u.fld[6]).rt_rtx); link; link = XEXP (link, 1)(((link)->u.fld[1]).rt_rtx)) | ||||||
2028 | if (REG_NOTE_KIND (link)((enum reg_note) ((machine_mode) (link)->mode)) == REG_INC | ||||||
2029 | && ((JUMP_P (i3)(((enum rtx_code) (i3)->code) == JUMP_INSN) && targetm.lra_p ()) | ||||||
2030 | || reg_used_between_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), insn, i3) | ||||||
2031 | || (pred != NULL_RTX(rtx) 0 | ||||||
2032 | && reg_overlap_mentioned_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), PATTERN (pred))) | ||||||
2033 | || (pred2 != NULL_RTX(rtx) 0 | ||||||
2034 | && reg_overlap_mentioned_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), PATTERN (pred2))) | ||||||
2035 | || (succ != NULL_RTX(rtx) 0 | ||||||
2036 | && reg_overlap_mentioned_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), PATTERN (succ))) | ||||||
2037 | || (succ2 != NULL_RTX(rtx) 0 | ||||||
2038 | && reg_overlap_mentioned_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), PATTERN (succ2))) | ||||||
2039 | || reg_overlap_mentioned_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), PATTERN (i3)))) | ||||||
2040 | return 0; | ||||||
2041 | |||||||
2042 | /* If we get here, we have passed all the tests and the combination is | ||||||
2043 | to be allowed. */ | ||||||
2044 | |||||||
2045 | *pdest = dest; | ||||||
2046 | *psrc = src; | ||||||
2047 | |||||||
2048 | return 1; | ||||||
2049 | } | ||||||
2050 | |||||||
2051 | /* LOC is the location within I3 that contains its pattern or the component | ||||||
2052 | of a PARALLEL of the pattern. We validate that it is valid for combining. | ||||||
2053 | |||||||
2054 | One problem is if I3 modifies its output, as opposed to replacing it | ||||||
2055 | entirely, we can't allow the output to contain I2DEST, I1DEST or I0DEST as | ||||||
2056 | doing so would produce an insn that is not equivalent to the original insns. | ||||||
2057 | |||||||
2058 | Consider: | ||||||
2059 | |||||||
2060 | (set (reg:DI 101) (reg:DI 100)) | ||||||
2061 | (set (subreg:SI (reg:DI 101) 0) <foo>) | ||||||
2062 | |||||||
2063 | This is NOT equivalent to: | ||||||
2064 | |||||||
2065 | (parallel [(set (subreg:SI (reg:DI 100) 0) <foo>) | ||||||
2066 | (set (reg:DI 101) (reg:DI 100))]) | ||||||
2067 | |||||||
2068 | Not only does this modify 100 (in which case it might still be valid | ||||||
2069 | if 100 were dead in I2), it sets 101 to the ORIGINAL value of 100. | ||||||
2070 | |||||||
2071 | We can also run into a problem if I2 sets a register that I1 | ||||||
2072 | uses and I1 gets directly substituted into I3 (not via I2). In that | ||||||
2073 | case, we would be getting the wrong value of I2DEST into I3, so we | ||||||
2074 | must reject the combination. This case occurs when I2 and I1 both | ||||||
2075 | feed into I3, rather than when I1 feeds into I2, which feeds into I3. | ||||||
2076 | If I1_NOT_IN_SRC is nonzero, it means that finding I1 in the source | ||||||
2077 | of a SET must prevent combination from occurring. The same situation | ||||||
2078 | can occur for I0, in which case I0_NOT_IN_SRC is set. | ||||||
2079 | |||||||
2080 | Before doing the above check, we first try to expand a field assignment | ||||||
2081 | into a set of logical operations. | ||||||
2082 | |||||||
2083 | If PI3_DEST_KILLED is nonzero, it is a pointer to a location in which | ||||||
2084 | we place a register that is both set and used within I3. If more than one | ||||||
2085 | such register is detected, we fail. | ||||||
2086 | |||||||
2087 | Return 1 if the combination is valid, zero otherwise. */ | ||||||
2088 | |||||||
2089 | static int | ||||||
2090 | combinable_i3pat (rtx_insn *i3, rtx *loc, rtx i2dest, rtx i1dest, rtx i0dest, | ||||||
2091 | int i1_not_in_src, int i0_not_in_src, rtx *pi3dest_killed) | ||||||
2092 | { | ||||||
2093 | rtx x = *loc; | ||||||
2094 | |||||||
2095 | if (GET_CODE (x)((enum rtx_code) (x)->code) == SET) | ||||||
2096 | { | ||||||
2097 | rtx set = x ; | ||||||
2098 | rtx dest = SET_DEST (set)(((set)->u.fld[0]).rt_rtx); | ||||||
2099 | rtx src = SET_SRC (set)(((set)->u.fld[1]).rt_rtx); | ||||||
2100 | rtx inner_dest = dest; | ||||||
2101 | rtx subdest; | ||||||
2102 | |||||||
2103 | while (GET_CODE (inner_dest)((enum rtx_code) (inner_dest)->code) == STRICT_LOW_PART | ||||||
2104 | || GET_CODE (inner_dest)((enum rtx_code) (inner_dest)->code) == SUBREG | ||||||
2105 | || GET_CODE (inner_dest)((enum rtx_code) (inner_dest)->code) == ZERO_EXTRACT) | ||||||
2106 | inner_dest = XEXP (inner_dest, 0)(((inner_dest)->u.fld[0]).rt_rtx); | ||||||
2107 | |||||||
2108 | /* Check for the case where I3 modifies its output, as discussed | ||||||
2109 | above. We don't want to prevent pseudos from being combined | ||||||
2110 | into the address of a MEM, so only prevent the combination if | ||||||
2111 | i1 or i2 set the same MEM. */ | ||||||
2112 | if ((inner_dest != dest && | ||||||
2113 | (!MEM_P (inner_dest)(((enum rtx_code) (inner_dest)->code) == MEM) | ||||||
2114 | || rtx_equal_p (i2dest, inner_dest) | ||||||
2115 | || (i1dest && rtx_equal_p (i1dest, inner_dest)) | ||||||
2116 | || (i0dest && rtx_equal_p (i0dest, inner_dest))) | ||||||
2117 | && (reg_overlap_mentioned_p (i2dest, inner_dest) | ||||||
2118 | || (i1dest && reg_overlap_mentioned_p (i1dest, inner_dest)) | ||||||
2119 | || (i0dest && reg_overlap_mentioned_p (i0dest, inner_dest)))) | ||||||
2120 | |||||||
2121 | /* This is the same test done in can_combine_p except we can't test | ||||||
2122 | all_adjacent; we don't have to, since this instruction will stay | ||||||
2123 | in place, thus we are not considering increasing the lifetime of | ||||||
2124 | INNER_DEST. | ||||||
2125 | |||||||
2126 | Also, if this insn sets a function argument, combining it with | ||||||
2127 | something that might need a spill could clobber a previous | ||||||
2128 | function argument; the all_adjacent test in can_combine_p also | ||||||
2129 | checks this; here, we do a more specific test for this case. */ | ||||||
2130 | |||||||
2131 | || (REG_P (inner_dest)(((enum rtx_code) (inner_dest)->code) == REG) | ||||||
2132 | && REGNO (inner_dest)(rhs_regno(inner_dest)) < FIRST_PSEUDO_REGISTER76 | ||||||
2133 | && !targetm.hard_regno_mode_ok (REGNO (inner_dest)(rhs_regno(inner_dest)), | ||||||
2134 | GET_MODE (inner_dest)((machine_mode) (inner_dest)->mode))) | ||||||
2135 | || (i1_not_in_src && reg_overlap_mentioned_p (i1dest, src)) | ||||||
2136 | || (i0_not_in_src && reg_overlap_mentioned_p (i0dest, src))) | ||||||
2137 | return 0; | ||||||
2138 | |||||||
2139 | /* If DEST is used in I3, it is being killed in this insn, so | ||||||
2140 | record that for later. We have to consider paradoxical | ||||||
2141 | subregs here, since they kill the whole register, but we | ||||||
2142 | ignore partial subregs, STRICT_LOW_PART, etc. | ||||||
2143 | Never add REG_DEAD notes for the FRAME_POINTER_REGNUM or the | ||||||
2144 | STACK_POINTER_REGNUM, since these are always considered to be | ||||||
2145 | live. Similarly for ARG_POINTER_REGNUM if it is fixed. */ | ||||||
2146 | subdest = dest; | ||||||
2147 | if (GET_CODE (subdest)((enum rtx_code) (subdest)->code) == SUBREG && !partial_subreg_p (subdest)) | ||||||
2148 | subdest = SUBREG_REG (subdest)(((subdest)->u.fld[0]).rt_rtx); | ||||||
2149 | if (pi3dest_killed | ||||||
2150 | && REG_P (subdest)(((enum rtx_code) (subdest)->code) == REG) | ||||||
2151 | && reg_referenced_p (subdest, PATTERN (i3)) | ||||||
2152 | && REGNO (subdest)(rhs_regno(subdest)) != FRAME_POINTER_REGNUM19 | ||||||
2153 | && (HARD_FRAME_POINTER_IS_FRAME_POINTER(6 == 19) | ||||||
2154 | || REGNO (subdest)(rhs_regno(subdest)) != HARD_FRAME_POINTER_REGNUM6) | ||||||
2155 | && (FRAME_POINTER_REGNUM19 == ARG_POINTER_REGNUM16 | ||||||
2156 | || (REGNO (subdest)(rhs_regno(subdest)) != ARG_POINTER_REGNUM16 | ||||||
2157 | || ! fixed_regs(this_target_hard_regs->x_fixed_regs) [REGNO (subdest)(rhs_regno(subdest))])) | ||||||
2158 | && REGNO (subdest)(rhs_regno(subdest)) != STACK_POINTER_REGNUM7) | ||||||
2159 | { | ||||||
2160 | if (*pi3dest_killed) | ||||||
2161 | return 0; | ||||||
2162 | |||||||
2163 | *pi3dest_killed = subdest; | ||||||
2164 | } | ||||||
2165 | } | ||||||
2166 | |||||||
2167 | else if (GET_CODE (x)((enum rtx_code) (x)->code) == PARALLEL) | ||||||
2168 | { | ||||||
2169 | int i; | ||||||
2170 | |||||||
2171 | for (i = 0; i < XVECLEN (x, 0)(((((x)->u.fld[0]).rt_rtvec))->num_elem); i++) | ||||||
2172 | if (! combinable_i3pat (i3, &XVECEXP (x, 0, i)(((((x)->u.fld[0]).rt_rtvec))->elem[i]), i2dest, i1dest, i0dest, | ||||||
2173 | i1_not_in_src, i0_not_in_src, pi3dest_killed)) | ||||||
2174 | return 0; | ||||||
2175 | } | ||||||
2176 | |||||||
2177 | return 1; | ||||||
2178 | } | ||||||
2179 | |||||||
2180 | /* Return 1 if X is an arithmetic expression that contains a multiplication | ||||||
2181 | and division. We don't count multiplications by powers of two here. */ | ||||||
2182 | |||||||
2183 | static int | ||||||
2184 | contains_muldiv (rtx x) | ||||||
2185 | { | ||||||
2186 | switch (GET_CODE (x)((enum rtx_code) (x)->code)) | ||||||
2187 | { | ||||||
2188 | case MOD: case DIV: case UMOD: case UDIV: | ||||||
2189 | return 1; | ||||||
2190 | |||||||
2191 | case MULT: | ||||||
2192 | return ! (CONST_INT_P (XEXP (x, 1))(((enum rtx_code) ((((x)->u.fld[1]).rt_rtx))->code) == CONST_INT ) | ||||||
2193 | && pow2p_hwi (UINTVAL (XEXP (x, 1))((unsigned long) (((((x)->u.fld[1]).rt_rtx))->u.hwint[0 ])))); | ||||||
2194 | default: | ||||||
2195 | if (BINARY_P (x)(((rtx_class[(int) (((enum rtx_code) (x)->code))]) & ( ~3)) == (RTX_COMPARE & (~3)))) | ||||||
2196 | return contains_muldiv (XEXP (x, 0)(((x)->u.fld[0]).rt_rtx)) | ||||||
2197 | || contains_muldiv (XEXP (x, 1)(((x)->u.fld[1]).rt_rtx)); | ||||||
2198 | |||||||
2199 | if (UNARY_P (x)((rtx_class[(int) (((enum rtx_code) (x)->code))]) == RTX_UNARY )) | ||||||
2200 | return contains_muldiv (XEXP (x, 0)(((x)->u.fld[0]).rt_rtx)); | ||||||
2201 | |||||||
2202 | return 0; | ||||||
2203 | } | ||||||
2204 | } | ||||||
2205 | |||||||
2206 | /* Determine whether INSN can be used in a combination. Return nonzero if | ||||||
2207 | not. This is used in try_combine to detect early some cases where we | ||||||
2208 | can't perform combinations. */ | ||||||
2209 | |||||||
2210 | static int | ||||||
2211 | cant_combine_insn_p (rtx_insn *insn) | ||||||
2212 | { | ||||||
2213 | rtx set; | ||||||
2214 | rtx src, dest; | ||||||
2215 | |||||||
2216 | /* If this isn't really an insn, we can't do anything. | ||||||
2217 | This can occur when flow deletes an insn that it has merged into an | ||||||
2218 | auto-increment address. */ | ||||||
2219 | if (!NONDEBUG_INSN_P (insn)((((enum rtx_code) (insn)->code) == INSN) || (((enum rtx_code ) (insn)->code) == JUMP_INSN) || (((enum rtx_code) (insn)-> code) == CALL_INSN))) | ||||||
2220 | return 1; | ||||||
2221 | |||||||
2222 | /* Never combine loads and stores involving hard regs that are likely | ||||||
2223 | to be spilled. The register allocator can usually handle such | ||||||
2224 | reg-reg moves by tying. If we allow the combiner to make | ||||||
2225 | substitutions of likely-spilled regs, reload might die. | ||||||
2226 | As an exception, we allow combinations involving fixed regs; these are | ||||||
2227 | not available to the register allocator so there's no risk involved. */ | ||||||
2228 | |||||||
2229 | set = single_set (insn); | ||||||
2230 | if (! set) | ||||||
2231 | return 0; | ||||||
2232 | src = SET_SRC (set)(((set)->u.fld[1]).rt_rtx); | ||||||
2233 | dest = SET_DEST (set)(((set)->u.fld[0]).rt_rtx); | ||||||
2234 | if (GET_CODE (src)((enum rtx_code) (src)->code) == SUBREG) | ||||||
2235 | src = SUBREG_REG (src)(((src)->u.fld[0]).rt_rtx); | ||||||
2236 | if (GET_CODE (dest)((enum rtx_code) (dest)->code) == SUBREG) | ||||||
2237 | dest = SUBREG_REG (dest)(((dest)->u.fld[0]).rt_rtx); | ||||||
2238 | if (REG_P (src)(((enum rtx_code) (src)->code) == REG) && REG_P (dest)(((enum rtx_code) (dest)->code) == REG) | ||||||
2239 | && ((HARD_REGISTER_P (src)((((rhs_regno(src))) < 76)) | ||||||
2240 | && ! TEST_HARD_REG_BIT (fixed_reg_set(this_target_hard_regs->x_fixed_reg_set), REGNO (src)(rhs_regno(src))) | ||||||
2241 | #ifdef LEAF_REGISTERS | ||||||
2242 | && ! LEAF_REGISTERS [REGNO (src)(rhs_regno(src))]) | ||||||
2243 | #else | ||||||
2244 | ) | ||||||
2245 | #endif | ||||||
2246 | || (HARD_REGISTER_P (dest)((((rhs_regno(dest))) < 76)) | ||||||
2247 | && ! TEST_HARD_REG_BIT (fixed_reg_set(this_target_hard_regs->x_fixed_reg_set), REGNO (dest)(rhs_regno(dest))) | ||||||
2248 | && targetm.class_likely_spilled_p (REGNO_REG_CLASS (REGNO (dest))(regclass_map[((rhs_regno(dest)))]))))) | ||||||
2249 | return 1; | ||||||
2250 | |||||||
2251 | return 0; | ||||||
2252 | } | ||||||
2253 | |||||||
2254 | struct likely_spilled_retval_info | ||||||
2255 | { | ||||||
2256 | unsigned regno, nregs; | ||||||
2257 | unsigned mask; | ||||||
2258 | }; | ||||||
2259 | |||||||
2260 | /* Called via note_stores by likely_spilled_retval_p. Remove from info->mask | ||||||
2261 | hard registers that are known to be written to / clobbered in full. */ | ||||||
2262 | static void | ||||||
2263 | likely_spilled_retval_1 (rtx x, const_rtx set, void *data) | ||||||
2264 | { | ||||||
2265 | struct likely_spilled_retval_info *const info = | ||||||
2266 | (struct likely_spilled_retval_info *) data; | ||||||
2267 | unsigned regno, nregs; | ||||||
2268 | unsigned new_mask; | ||||||
2269 | |||||||
2270 | if (!REG_P (XEXP (set, 0))(((enum rtx_code) ((((set)->u.fld[0]).rt_rtx))->code) == REG)) | ||||||
2271 | return; | ||||||
2272 | regno = REGNO (x)(rhs_regno(x)); | ||||||
2273 | if (regno >= info->regno + info->nregs) | ||||||
2274 | return; | ||||||
2275 | nregs = REG_NREGS (x)((&(x)->u.reg)->nregs); | ||||||
2276 | if (regno + nregs <= info->regno) | ||||||
2277 | return; | ||||||
2278 | new_mask = (2U << (nregs - 1)) - 1; | ||||||
2279 | if (regno < info->regno) | ||||||
2280 | new_mask >>= info->regno - regno; | ||||||
2281 | else | ||||||
2282 | new_mask <<= regno - info->regno; | ||||||
2283 | info->mask &= ~new_mask; | ||||||
2284 | } | ||||||
2285 | |||||||
2286 | /* Return nonzero iff part of the return value is live during INSN, and | ||||||
2287 | it is likely spilled. This can happen when more than one insn is needed | ||||||
2288 | to copy the return value, e.g. when we consider to combine into the | ||||||
2289 | second copy insn for a complex value. */ | ||||||
2290 | |||||||
2291 | static int | ||||||
2292 | likely_spilled_retval_p (rtx_insn *insn) | ||||||
2293 | { | ||||||
2294 | rtx_insn *use = BB_END (this_basic_block)(this_basic_block)->il.x.rtl->end_; | ||||||
2295 | rtx reg; | ||||||
2296 | rtx_insn *p; | ||||||
2297 | unsigned regno, nregs; | ||||||
2298 | /* We assume here that no machine mode needs more than | ||||||
2299 | 32 hard registers when the value overlaps with a register | ||||||
2300 | for which TARGET_FUNCTION_VALUE_REGNO_P is true. */ | ||||||
2301 | unsigned mask; | ||||||
2302 | struct likely_spilled_retval_info info; | ||||||
2303 | |||||||
2304 | if (!NONJUMP_INSN_P (use)(((enum rtx_code) (use)->code) == INSN) || GET_CODE (PATTERN (use))((enum rtx_code) (PATTERN (use))->code) != USE || insn == use) | ||||||
2305 | return 0; | ||||||
2306 | reg = XEXP (PATTERN (use), 0)(((PATTERN (use))->u.fld[0]).rt_rtx); | ||||||
2307 | if (!REG_P (reg)(((enum rtx_code) (reg)->code) == REG) || !targetm.calls.function_value_regno_p (REGNO (reg)(rhs_regno(reg)))) | ||||||
2308 | return 0; | ||||||
2309 | regno = REGNO (reg)(rhs_regno(reg)); | ||||||
2310 | nregs = REG_NREGS (reg)((&(reg)->u.reg)->nregs); | ||||||
2311 | if (nregs == 1) | ||||||
2312 | return 0; | ||||||
2313 | mask = (2U << (nregs - 1)) - 1; | ||||||
2314 | |||||||
2315 | /* Disregard parts of the return value that are set later. */ | ||||||
2316 | info.regno = regno; | ||||||
2317 | info.nregs = nregs; | ||||||
2318 | info.mask = mask; | ||||||
2319 | for (p = PREV_INSN (use); info.mask && p != insn; p = PREV_INSN (p)) | ||||||
2320 | if (INSN_P (p)(((((enum rtx_code) (p)->code) == INSN) || (((enum rtx_code ) (p)->code) == JUMP_INSN) || (((enum rtx_code) (p)->code ) == CALL_INSN)) || (((enum rtx_code) (p)->code) == DEBUG_INSN ))) | ||||||
2321 | note_stores (p, likely_spilled_retval_1, &info); | ||||||
2322 | mask = info.mask; | ||||||
2323 | |||||||
2324 | /* Check if any of the (probably) live return value registers is | ||||||
2325 | likely spilled. */ | ||||||
2326 | nregs --; | ||||||
2327 | do | ||||||
2328 | { | ||||||
2329 | if ((mask & 1 << nregs) | ||||||
2330 | && targetm.class_likely_spilled_p (REGNO_REG_CLASS (regno + nregs)(regclass_map[(regno + nregs)]))) | ||||||
2331 | return 1; | ||||||
2332 | } while (nregs--); | ||||||
2333 | return 0; | ||||||
2334 | } | ||||||
2335 | |||||||
2336 | /* Adjust INSN after we made a change to its destination. | ||||||
2337 | |||||||
2338 | Changing the destination can invalidate notes that say something about | ||||||
2339 | the results of the insn and a LOG_LINK pointing to the insn. */ | ||||||
2340 | |||||||
2341 | static void | ||||||
2342 | adjust_for_new_dest (rtx_insn *insn) | ||||||
2343 | { | ||||||
2344 | /* For notes, be conservative and simply remove them. */ | ||||||
2345 | remove_reg_equal_equiv_notes (insn, true); | ||||||
2346 | |||||||
2347 | /* The new insn will have a destination that was previously the destination | ||||||
2348 | of an insn just above it. Call distribute_links to make a LOG_LINK from | ||||||
2349 | the next use of that destination. */ | ||||||
2350 | |||||||
2351 | rtx set = single_set (insn); | ||||||
2352 | gcc_assert (set)((void)(!(set) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 2352, __FUNCTION__), 0 : 0)); | ||||||
2353 | |||||||
2354 | rtx reg = SET_DEST (set)(((set)->u.fld[0]).rt_rtx); | ||||||
2355 | |||||||
2356 | while (GET_CODE (reg)((enum rtx_code) (reg)->code) == ZERO_EXTRACT | ||||||
2357 | || GET_CODE (reg)((enum rtx_code) (reg)->code) == STRICT_LOW_PART | ||||||
2358 | || GET_CODE (reg)((enum rtx_code) (reg)->code) == SUBREG) | ||||||
2359 | reg = XEXP (reg, 0)(((reg)->u.fld[0]).rt_rtx); | ||||||
2360 | gcc_assert (REG_P (reg))((void)(!((((enum rtx_code) (reg)->code) == REG)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 2360, __FUNCTION__), 0 : 0)); | ||||||
2361 | |||||||
2362 | distribute_links (alloc_insn_link (insn, REGNO (reg)(rhs_regno(reg)), NULLnullptr)); | ||||||
2363 | |||||||
2364 | df_insn_rescan (insn); | ||||||
2365 | } | ||||||
2366 | |||||||
2367 | /* Return TRUE if combine can reuse reg X in mode MODE. | ||||||
2368 | ADDED_SETS is nonzero if the original set is still required. */ | ||||||
2369 | static bool | ||||||
2370 | can_change_dest_mode (rtx x, int added_sets, machine_mode mode) | ||||||
2371 | { | ||||||
2372 | unsigned int regno; | ||||||
2373 | |||||||
2374 | if (!REG_P (x)(((enum rtx_code) (x)->code) == REG)) | ||||||
2375 | return false; | ||||||
2376 | |||||||
2377 | /* Don't change between modes with different underlying register sizes, | ||||||
2378 | since this could lead to invalid subregs. */ | ||||||
2379 | if (maybe_ne (REGMODE_NATURAL_SIZE (mode)ix86_regmode_natural_size (mode), | ||||||
2380 | REGMODE_NATURAL_SIZE (GET_MODE (x))ix86_regmode_natural_size (((machine_mode) (x)->mode)))) | ||||||
2381 | return false; | ||||||
2382 | |||||||
2383 | regno = REGNO (x)(rhs_regno(x)); | ||||||
2384 | /* Allow hard registers if the new mode is legal, and occupies no more | ||||||
2385 | registers than the old mode. */ | ||||||
2386 | if (regno < FIRST_PSEUDO_REGISTER76) | ||||||
2387 | return (targetm.hard_regno_mode_ok (regno, mode) | ||||||
2388 | && REG_NREGS (x)((&(x)->u.reg)->nregs) >= hard_regno_nregs (regno, mode)); | ||||||
2389 | |||||||
2390 | /* Or a pseudo that is only used once. */ | ||||||
2391 | return (regno < reg_n_sets_max | ||||||
2392 | && REG_N_SETS (regno) == 1 | ||||||
2393 | && !added_sets | ||||||
2394 | && !REG_USERVAR_P (x)(__extension__ ({ __typeof ((x)) const _rtx = ((x)); if (((enum rtx_code) (_rtx)->code) != REG) rtl_check_failed_flag ("REG_USERVAR_P" , _rtx, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 2394, __FUNCTION__); _rtx; })->volatil)); | ||||||
2395 | } | ||||||
2396 | |||||||
2397 | |||||||
2398 | /* Check whether X, the destination of a set, refers to part of | ||||||
2399 | the register specified by REG. */ | ||||||
2400 | |||||||
2401 | static bool | ||||||
2402 | reg_subword_p (rtx x, rtx reg) | ||||||
2403 | { | ||||||
2404 | /* Check that reg is an integer mode register. */ | ||||||
2405 | if (!REG_P (reg)(((enum rtx_code) (reg)->code) == REG) || GET_MODE_CLASS (GET_MODE (reg))((enum mode_class) mode_class[((machine_mode) (reg)->mode) ]) != MODE_INT) | ||||||
2406 | return false; | ||||||
2407 | |||||||
2408 | if (GET_CODE (x)((enum rtx_code) (x)->code) == STRICT_LOW_PART | ||||||
2409 | || GET_CODE (x)((enum rtx_code) (x)->code) == ZERO_EXTRACT) | ||||||
2410 | x = XEXP (x, 0)(((x)->u.fld[0]).rt_rtx); | ||||||
2411 | |||||||
2412 | return GET_CODE (x)((enum rtx_code) (x)->code) == SUBREG | ||||||
2413 | && !paradoxical_subreg_p (x) | ||||||
2414 | && SUBREG_REG (x)(((x)->u.fld[0]).rt_rtx) == reg | ||||||
2415 | && GET_MODE_CLASS (GET_MODE (x))((enum mode_class) mode_class[((machine_mode) (x)->mode)]) == MODE_INT; | ||||||
2416 | } | ||||||
2417 | |||||||
2418 | /* Return whether PAT is a PARALLEL of exactly N register SETs followed | ||||||
2419 | by an arbitrary number of CLOBBERs. */ | ||||||
2420 | static bool | ||||||
2421 | is_parallel_of_n_reg_sets (rtx pat, int n) | ||||||
2422 | { | ||||||
2423 | if (GET_CODE (pat)((enum rtx_code) (pat)->code) != PARALLEL) | ||||||
2424 | return false; | ||||||
2425 | |||||||
2426 | int len = XVECLEN (pat, 0)(((((pat)->u.fld[0]).rt_rtvec))->num_elem); | ||||||
2427 | if (len < n) | ||||||
2428 | return false; | ||||||
2429 | |||||||
2430 | int i; | ||||||
2431 | for (i = 0; i < n; i++) | ||||||
2432 | if (GET_CODE (XVECEXP (pat, 0, i))((enum rtx_code) ((((((pat)->u.fld[0]).rt_rtvec))->elem [i]))->code) != SET | ||||||
2433 | || !REG_P (SET_DEST (XVECEXP (pat, 0, i)))(((enum rtx_code) (((((((((pat)->u.fld[0]).rt_rtvec))-> elem[i]))->u.fld[0]).rt_rtx))->code) == REG)) | ||||||
2434 | return false; | ||||||
2435 | for ( ; i < len; i++) | ||||||
2436 | switch (GET_CODE (XVECEXP (pat, 0, i))((enum rtx_code) ((((((pat)->u.fld[0]).rt_rtvec))->elem [i]))->code)) | ||||||
2437 | { | ||||||
2438 | case CLOBBER: | ||||||
2439 | if (XEXP (XVECEXP (pat, 0, i), 0)((((((((pat)->u.fld[0]).rt_rtvec))->elem[i]))->u.fld [0]).rt_rtx) == const0_rtx(const_int_rtx[64])) | ||||||
2440 | return false; | ||||||
2441 | break; | ||||||
2442 | default: | ||||||
2443 | return false; | ||||||
2444 | } | ||||||
2445 | return true; | ||||||
2446 | } | ||||||
2447 | |||||||
2448 | /* Return whether INSN, a PARALLEL of N register SETs (and maybe some | ||||||
2449 | CLOBBERs), can be split into individual SETs in that order, without | ||||||
2450 | changing semantics. */ | ||||||
2451 | static bool | ||||||
2452 | can_split_parallel_of_n_reg_sets (rtx_insn *insn, int n) | ||||||
2453 | { | ||||||
2454 | if (!insn_nothrow_p (insn)) | ||||||
2455 | return false; | ||||||
2456 | |||||||
2457 | rtx pat = PATTERN (insn); | ||||||
2458 | |||||||
2459 | int i, j; | ||||||
2460 | for (i = 0; i < n; i++) | ||||||
2461 | { | ||||||
2462 | if (side_effects_p (SET_SRC (XVECEXP (pat, 0, i))((((((((pat)->u.fld[0]).rt_rtvec))->elem[i]))->u.fld [1]).rt_rtx))) | ||||||
2463 | return false; | ||||||
2464 | |||||||
2465 | rtx reg = SET_DEST (XVECEXP (pat, 0, i))((((((((pat)->u.fld[0]).rt_rtvec))->elem[i]))->u.fld [0]).rt_rtx); | ||||||
2466 | |||||||
2467 | for (j = i + 1; j < n; j++) | ||||||
2468 | if (reg_referenced_p (reg, XVECEXP (pat, 0, j)(((((pat)->u.fld[0]).rt_rtvec))->elem[j]))) | ||||||
2469 | return false; | ||||||
2470 | } | ||||||
2471 | |||||||
2472 | return true; | ||||||
2473 | } | ||||||
2474 | |||||||
2475 | /* Return whether X is just a single_set, with the source | ||||||
2476 | a general_operand. */ | ||||||
2477 | static bool | ||||||
2478 | is_just_move (rtx_insn *x) | ||||||
2479 | { | ||||||
2480 | rtx set = single_set (x); | ||||||
2481 | if (!set) | ||||||
2482 | return false; | ||||||
2483 | |||||||
2484 | return general_operand (SET_SRC (set)(((set)->u.fld[1]).rt_rtx), VOIDmode((void) 0, E_VOIDmode)); | ||||||
2485 | } | ||||||
2486 | |||||||
2487 | /* Callback function to count autoincs. */ | ||||||
2488 | |||||||
2489 | static int | ||||||
2490 | count_auto_inc (rtx, rtx, rtx, rtx, rtx, void *arg) | ||||||
2491 | { | ||||||
2492 | (*((int *) arg))++; | ||||||
2493 | |||||||
2494 | return 0; | ||||||
2495 | } | ||||||
2496 | |||||||
2497 | /* Try to combine the insns I0, I1 and I2 into I3. | ||||||
2498 | Here I0, I1 and I2 appear earlier than I3. | ||||||
2499 | I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into | ||||||
2500 | I3. | ||||||
2501 | |||||||
2502 | If we are combining more than two insns and the resulting insn is not | ||||||
2503 | recognized, try splitting it into two insns. If that happens, I2 and I3 | ||||||
2504 | are retained and I1/I0 are pseudo-deleted by turning them into a NOTE. | ||||||
2505 | Otherwise, I0, I1 and I2 are pseudo-deleted. | ||||||
2506 | |||||||
2507 | Return 0 if the combination does not work. Then nothing is changed. | ||||||
2508 | If we did the combination, return the insn at which combine should | ||||||
2509 | resume scanning. | ||||||
2510 | |||||||
2511 | Set NEW_DIRECT_JUMP_P to a nonzero value if try_combine creates a | ||||||
2512 | new direct jump instruction. | ||||||
2513 | |||||||
2514 | LAST_COMBINED_INSN is either I3, or some insn after I3 that has | ||||||
2515 | been I3 passed to an earlier try_combine within the same basic | ||||||
2516 | block. */ | ||||||
2517 | |||||||
2518 | static rtx_insn * | ||||||
2519 | try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, | ||||||
2520 | int *new_direct_jump_p, rtx_insn *last_combined_insn) | ||||||
2521 | { | ||||||
2522 | /* New patterns for I3 and I2, respectively. */ | ||||||
2523 | rtx newpat, newi2pat = 0; | ||||||
2524 | rtvec newpat_vec_with_clobbers = 0; | ||||||
2525 | int substed_i2 = 0, substed_i1 = 0, substed_i0 = 0; | ||||||
2526 | /* Indicates need to preserve SET in I0, I1 or I2 in I3 if it is not | ||||||
2527 | dead. */ | ||||||
2528 | int added_sets_0, added_sets_1, added_sets_2; | ||||||
2529 | /* Total number of SETs to put into I3. */ | ||||||
2530 | int total_sets; | ||||||
2531 | /* Nonzero if I2's or I1's body now appears in I3. */ | ||||||
2532 | int i2_is_used = 0, i1_is_used = 0; | ||||||
2533 | /* INSN_CODEs for new I3, new I2, and user of condition code. */ | ||||||
2534 | int insn_code_number, i2_code_number = 0, other_code_number = 0; | ||||||
2535 | /* Contains I3 if the destination of I3 is used in its source, which means | ||||||
2536 | that the old life of I3 is being killed. If that usage is placed into | ||||||
2537 | I2 and not in I3, a REG_DEAD note must be made. */ | ||||||
2538 | rtx i3dest_killed = 0; | ||||||
2539 | /* SET_DEST and SET_SRC of I2, I1 and I0. */ | ||||||
2540 | rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0, i0dest = 0, i0src = 0; | ||||||
2541 | /* Copy of SET_SRC of I1 and I0, if needed. */ | ||||||
2542 | rtx i1src_copy = 0, i0src_copy = 0, i0src_copy2 = 0; | ||||||
2543 | /* Set if I2DEST was reused as a scratch register. */ | ||||||
2544 | bool i2scratch = false; | ||||||
2545 | /* The PATTERNs of I0, I1, and I2, or a copy of them in certain cases. */ | ||||||
2546 | rtx i0pat = 0, i1pat = 0, i2pat = 0; | ||||||
2547 | /* Indicates if I2DEST or I1DEST is in I2SRC or I1_SRC. */ | ||||||
2548 | int i2dest_in_i2src = 0, i1dest_in_i1src = 0, i2dest_in_i1src = 0; | ||||||
2549 | int i0dest_in_i0src = 0, i1dest_in_i0src = 0, i2dest_in_i0src = 0; | ||||||
2550 | int i2dest_killed = 0, i1dest_killed = 0, i0dest_killed = 0; | ||||||
2551 | int i1_feeds_i2_n = 0, i0_feeds_i2_n = 0, i0_feeds_i1_n = 0; | ||||||
2552 | /* Notes that must be added to REG_NOTES in I3 and I2. */ | ||||||
2553 | rtx new_i3_notes, new_i2_notes; | ||||||
| |||||||
2554 | /* Notes that we substituted I3 into I2 instead of the normal case. */ | ||||||
2555 | int i3_subst_into_i2 = 0; | ||||||
2556 | /* Notes that I1, I2 or I3 is a MULT operation. */ | ||||||
2557 | int have_mult = 0; | ||||||
2558 | int swap_i2i3 = 0; | ||||||
2559 | int split_i2i3 = 0; | ||||||
2560 | int changed_i3_dest = 0; | ||||||
2561 | bool i2_was_move = false, i3_was_move = false; | ||||||
2562 | int n_auto_inc = 0; | ||||||
2563 | |||||||
2564 | int maxreg; | ||||||
2565 | rtx_insn *temp_insn; | ||||||
2566 | rtx temp_expr; | ||||||
2567 | struct insn_link *link; | ||||||
2568 | rtx other_pat = 0; | ||||||
2569 | rtx new_other_notes; | ||||||
2570 | int i; | ||||||
2571 | scalar_int_mode dest_mode, temp_mode; | ||||||
2572 | bool has_non_call_exception = false; | ||||||
2573 | |||||||
2574 | /* Immediately return if any of I0,I1,I2 are the same insn (I3 can | ||||||
2575 | never be). */ | ||||||
2576 | if (i1 == i2 || i0 == i2 || (i0 && i0 == i1)) | ||||||
2577 | return 0; | ||||||
2578 | |||||||
2579 | /* Only try four-insn combinations when there's high likelihood of | ||||||
2580 | success. Look for simple insns, such as loads of constants or | ||||||
2581 | binary operations involving a constant. */ | ||||||
2582 | if (i0
| ||||||
2583 | { | ||||||
2584 | int i; | ||||||
2585 | int ngood = 0; | ||||||
2586 | int nshift = 0; | ||||||
2587 | rtx set0, set3; | ||||||
2588 | |||||||
2589 | if (!flag_expensive_optimizationsglobal_options.x_flag_expensive_optimizations) | ||||||
2590 | return 0; | ||||||
2591 | |||||||
2592 | for (i = 0; i < 4; i++) | ||||||
2593 | { | ||||||
2594 | rtx_insn *insn = i == 0 ? i0 : i == 1 ? i1 : i == 2 ? i2 : i3; | ||||||
2595 | rtx set = single_set (insn); | ||||||
2596 | rtx src; | ||||||
2597 | if (!set) | ||||||
2598 | continue; | ||||||
2599 | src = SET_SRC (set)(((set)->u.fld[1]).rt_rtx); | ||||||
2600 | if (CONSTANT_P (src)((rtx_class[(int) (((enum rtx_code) (src)->code))]) == RTX_CONST_OBJ )) | ||||||
2601 | { | ||||||
2602 | ngood += 2; | ||||||
2603 | break; | ||||||
2604 | } | ||||||
2605 | else if (BINARY_P (src)(((rtx_class[(int) (((enum rtx_code) (src)->code))]) & (~3)) == (RTX_COMPARE & (~3))) && CONSTANT_P (XEXP (src, 1))((rtx_class[(int) (((enum rtx_code) ((((src)->u.fld[1]).rt_rtx ))->code))]) == RTX_CONST_OBJ)) | ||||||
2606 | ngood++; | ||||||
2607 | else if (GET_CODE (src)((enum rtx_code) (src)->code) == ASHIFT || GET_CODE (src)((enum rtx_code) (src)->code) == ASHIFTRT | ||||||
2608 | || GET_CODE (src)((enum rtx_code) (src)->code) == LSHIFTRT) | ||||||
2609 | nshift++; | ||||||
2610 | } | ||||||
2611 | |||||||
2612 | /* If I0 loads a memory and I3 sets the same memory, then I1 and I2 | ||||||
2613 | are likely manipulating its value. Ideally we'll be able to combine | ||||||
2614 | all four insns into a bitfield insertion of some kind. | ||||||
2615 | |||||||
2616 | Note the source in I0 might be inside a sign/zero extension and the | ||||||
2617 | memory modes in I0 and I3 might be different. So extract the address | ||||||
2618 | from the destination of I3 and search for it in the source of I0. | ||||||
2619 | |||||||
2620 | In the event that there's a match but the source/dest do not actually | ||||||
2621 | refer to the same memory, the worst that happens is we try some | ||||||
2622 | combinations that we wouldn't have otherwise. */ | ||||||
2623 | if ((set0 = single_set (i0)) | ||||||
2624 | /* Ensure the source of SET0 is a MEM, possibly buried inside | ||||||
2625 | an extension. */ | ||||||
2626 | && (GET_CODE (SET_SRC (set0))((enum rtx_code) ((((set0)->u.fld[1]).rt_rtx))->code) == MEM | ||||||
2627 | || ((GET_CODE (SET_SRC (set0))((enum rtx_code) ((((set0)->u.fld[1]).rt_rtx))->code) == ZERO_EXTEND | ||||||
2628 | || GET_CODE (SET_SRC (set0))((enum rtx_code) ((((set0)->u.fld[1]).rt_rtx))->code) == SIGN_EXTEND) | ||||||
2629 | && GET_CODE (XEXP (SET_SRC (set0), 0))((enum rtx_code) (((((((set0)->u.fld[1]).rt_rtx))->u.fld [0]).rt_rtx))->code) == MEM)) | ||||||
2630 | && (set3 = single_set (i3)) | ||||||
2631 | /* Ensure the destination of SET3 is a MEM. */ | ||||||
2632 | && GET_CODE (SET_DEST (set3))((enum rtx_code) ((((set3)->u.fld[0]).rt_rtx))->code) == MEM | ||||||
2633 | /* Would it be better to extract the base address for the MEM | ||||||
2634 | in SET3 and look for that? I don't have cases where it matters | ||||||
2635 | but I could envision such cases. */ | ||||||
2636 | && rtx_referenced_p (XEXP (SET_DEST (set3), 0)((((((set3)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx), SET_SRC (set0)(((set0)->u.fld[1]).rt_rtx))) | ||||||
2637 | ngood += 2; | ||||||
2638 | |||||||
2639 | if (ngood < 2 && nshift < 2) | ||||||
2640 | return 0; | ||||||
2641 | } | ||||||
2642 | |||||||
2643 | /* Exit early if one of the insns involved can't be used for | ||||||
2644 | combinations. */ | ||||||
2645 | if (CALL_P (i2)(((enum rtx_code) (i2)->code) == CALL_INSN) | ||||||
2646 | || (i1 && CALL_P (i1)(((enum rtx_code) (i1)->code) == CALL_INSN)) | ||||||
2647 | || (i0
| ||||||
2648 | || cant_combine_insn_p (i3) | ||||||
2649 | || cant_combine_insn_p (i2) | ||||||
2650 | || (i1
| ||||||
2651 | || (i0
| ||||||
2652 | || likely_spilled_retval_p (i3)) | ||||||
2653 | return 0; | ||||||
2654 | |||||||
2655 | combine_attempts++; | ||||||
2656 | undobuf.other_insn = 0; | ||||||
2657 | |||||||
2658 | /* Reset the hard register usage information. */ | ||||||
2659 | CLEAR_HARD_REG_SET (newpat_used_regs); | ||||||
2660 | |||||||
2661 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||||
2662 | { | ||||||
2663 | if (i0) | ||||||
2664 | fprintf (dump_file, "\nTrying %d, %d, %d -> %d:\n", | ||||||
2665 | INSN_UID (i0), INSN_UID (i1), INSN_UID (i2), INSN_UID (i3)); | ||||||
2666 | else if (i1) | ||||||
2667 | fprintf (dump_file, "\nTrying %d, %d -> %d:\n", | ||||||
2668 | INSN_UID (i1), INSN_UID (i2), INSN_UID (i3)); | ||||||
2669 | else | ||||||
2670 | fprintf (dump_file, "\nTrying %d -> %d:\n", | ||||||
2671 | INSN_UID (i2), INSN_UID (i3)); | ||||||
2672 | |||||||
2673 | if (i0) | ||||||
2674 | dump_insn_slim (dump_file, i0); | ||||||
2675 | if (i1) | ||||||
2676 | dump_insn_slim (dump_file, i1); | ||||||
2677 | dump_insn_slim (dump_file, i2); | ||||||
2678 | dump_insn_slim (dump_file, i3); | ||||||
2679 | } | ||||||
2680 | |||||||
2681 | /* If multiple insns feed into one of I2 or I3, they can be in any | ||||||
2682 | order. To simplify the code below, reorder them in sequence. */ | ||||||
2683 | if (i0
| ||||||
2684 | std::swap (i0, i2); | ||||||
2685 | if (i0
| ||||||
2686 | std::swap (i0, i1); | ||||||
2687 | if (i1
| ||||||
2688 | std::swap (i1, i2); | ||||||
2689 | |||||||
2690 | added_links_insn = 0; | ||||||
2691 | added_notes_insn = 0; | ||||||
2692 | |||||||
2693 | /* First check for one important special case that the code below will | ||||||
2694 | not handle. Namely, the case where I1 is zero, I2 is a PARALLEL | ||||||
2695 | and I3 is a SET whose SET_SRC is a SET_DEST in I2. In that case, | ||||||
2696 | we may be able to replace that destination with the destination of I3. | ||||||
2697 | This occurs in the common code where we compute both a quotient and | ||||||
2698 | remainder into a structure, in which case we want to do the computation | ||||||
2699 | directly into the structure to avoid register-register copies. | ||||||
2700 | |||||||
2701 | Note that this case handles both multiple sets in I2 and also cases | ||||||
2702 | where I2 has a number of CLOBBERs inside the PARALLEL. | ||||||
2703 | |||||||
2704 | We make very conservative checks below and only try to handle the | ||||||
2705 | most common cases of this. For example, we only handle the case | ||||||
2706 | where I2 and I3 are adjacent to avoid making difficult register | ||||||
2707 | usage tests. */ | ||||||
2708 | |||||||
2709 | if (i1
| ||||||
2710 | && REG_P (SET_SRC (PATTERN (i3)))(((enum rtx_code) ((((PATTERN (i3))->u.fld[1]).rt_rtx))-> code) == REG) | ||||||
2711 | && REGNO (SET_SRC (PATTERN (i3)))(rhs_regno((((PATTERN (i3))->u.fld[1]).rt_rtx))) >= FIRST_PSEUDO_REGISTER76 | ||||||
2712 | && find_reg_note (i3, REG_DEAD, SET_SRC (PATTERN (i3))(((PATTERN (i3))->u.fld[1]).rt_rtx)) | ||||||
2713 | && GET_CODE (PATTERN (i2))((enum rtx_code) (PATTERN (i2))->code) == PARALLEL | ||||||
2714 | && ! side_effects_p (SET_DEST (PATTERN (i3))(((PATTERN (i3))->u.fld[0]).rt_rtx)) | ||||||
2715 | /* If the dest of I3 is a ZERO_EXTRACT or STRICT_LOW_PART, the code | ||||||
2716 | below would need to check what is inside (and reg_overlap_mentioned_p | ||||||
2717 | doesn't support those codes anyway). Don't allow those destinations; | ||||||
2718 | the resulting insn isn't likely to be recognized anyway. */ | ||||||
2719 | && GET_CODE (SET_DEST (PATTERN (i3)))((enum rtx_code) ((((PATTERN (i3))->u.fld[0]).rt_rtx))-> code) != ZERO_EXTRACT | ||||||
2720 | && GET_CODE (SET_DEST (PATTERN (i3)))((enum rtx_code) ((((PATTERN (i3))->u.fld[0]).rt_rtx))-> code) != STRICT_LOW_PART | ||||||
2721 | && ! reg_overlap_mentioned_p (SET_SRC (PATTERN (i3))(((PATTERN (i3))->u.fld[1]).rt_rtx), | ||||||
2722 | SET_DEST (PATTERN (i3))(((PATTERN (i3))->u.fld[0]).rt_rtx)) | ||||||
2723 | && next_active_insn (i2) == i3) | ||||||
2724 | { | ||||||
2725 | rtx p2 = PATTERN (i2); | ||||||
2726 | |||||||
2727 | /* Make sure that the destination of I3, | ||||||
2728 | which we are going to substitute into one output of I2, | ||||||
2729 | is not used within another output of I2. We must avoid making this: | ||||||
2730 | (parallel [(set (mem (reg 69)) ...) | ||||||
2731 | (set (reg 69) ...)]) | ||||||
2732 | which is not well-defined as to order of actions. | ||||||
2733 | (Besides, reload can't handle output reloads for this.) | ||||||
2734 | |||||||
2735 | The problem can also happen if the dest of I3 is a memory ref, | ||||||
2736 | if another dest in I2 is an indirect memory ref. | ||||||
2737 | |||||||
2738 | Neither can this PARALLEL be an asm. We do not allow combining | ||||||
2739 | that usually (see can_combine_p), so do not here either. */ | ||||||
2740 | bool ok = true; | ||||||
2741 | for (i = 0; ok && i < XVECLEN (p2, 0)(((((p2)->u.fld[0]).rt_rtvec))->num_elem); i++) | ||||||
2742 | { | ||||||
2743 | if ((GET_CODE (XVECEXP (p2, 0, i))((enum rtx_code) ((((((p2)->u.fld[0]).rt_rtvec))->elem[ i]))->code) == SET | ||||||
2744 | || GET_CODE (XVECEXP (p2, 0, i))((enum rtx_code) ((((((p2)->u.fld[0]).rt_rtvec))->elem[ i]))->code) == CLOBBER) | ||||||
2745 | && reg_overlap_mentioned_p (SET_DEST (PATTERN (i3))(((PATTERN (i3))->u.fld[0]).rt_rtx), | ||||||
2746 | SET_DEST (XVECEXP (p2, 0, i))((((((((p2)->u.fld[0]).rt_rtvec))->elem[i]))->u.fld[ 0]).rt_rtx))) | ||||||
2747 | ok = false; | ||||||
2748 | else if (GET_CODE (XVECEXP (p2, 0, i))((enum rtx_code) ((((((p2)->u.fld[0]).rt_rtvec))->elem[ i]))->code) == SET | ||||||
2749 | && GET_CODE (SET_SRC (XVECEXP (p2, 0, i)))((enum rtx_code) (((((((((p2)->u.fld[0]).rt_rtvec))->elem [i]))->u.fld[1]).rt_rtx))->code) == ASM_OPERANDS) | ||||||
2750 | ok = false; | ||||||
2751 | } | ||||||
2752 | |||||||
2753 | if (ok) | ||||||
2754 | for (i = 0; i < XVECLEN (p2, 0)(((((p2)->u.fld[0]).rt_rtvec))->num_elem); i++) | ||||||
2755 | if (GET_CODE (XVECEXP (p2, 0, i))((enum rtx_code) ((((((p2)->u.fld[0]).rt_rtvec))->elem[ i]))->code) == SET | ||||||
2756 | && SET_DEST (XVECEXP (p2, 0, i))((((((((p2)->u.fld[0]).rt_rtvec))->elem[i]))->u.fld[ 0]).rt_rtx) == SET_SRC (PATTERN (i3))(((PATTERN (i3))->u.fld[1]).rt_rtx)) | ||||||
2757 | { | ||||||
2758 | combine_merges++; | ||||||
2759 | |||||||
2760 | subst_insn = i3; | ||||||
2761 | subst_low_luid = DF_INSN_LUID (i2)((((df->insns[(INSN_UID (i2))]))->luid)); | ||||||
2762 | |||||||
2763 | added_sets_2 = added_sets_1 = added_sets_0 = 0; | ||||||
2764 | i2src = SET_SRC (XVECEXP (p2, 0, i))((((((((p2)->u.fld[0]).rt_rtvec))->elem[i]))->u.fld[ 1]).rt_rtx); | ||||||
2765 | i2dest = SET_DEST (XVECEXP (p2, 0, i))((((((((p2)->u.fld[0]).rt_rtvec))->elem[i]))->u.fld[ 0]).rt_rtx); | ||||||
2766 | i2dest_killed = dead_or_set_p (i2, i2dest); | ||||||
2767 | |||||||
2768 | /* Replace the dest in I2 with our dest and make the resulting | ||||||
2769 | insn the new pattern for I3. Then skip to where we validate | ||||||
2770 | the pattern. Everything was set up above. */ | ||||||
2771 | SUBST (SET_DEST (XVECEXP (p2, 0, i)), SET_DEST (PATTERN (i3)))do_SUBST (&(((((((((p2)->u.fld[0]).rt_rtvec))->elem [i]))->u.fld[0]).rt_rtx)), ((((PATTERN (i3))->u.fld[0]) .rt_rtx))); | ||||||
2772 | newpat = p2; | ||||||
2773 | i3_subst_into_i2 = 1; | ||||||
2774 | goto validate_replacement; | ||||||
2775 | } | ||||||
2776 | } | ||||||
2777 | |||||||
2778 | /* If I2 is setting a pseudo to a constant and I3 is setting some | ||||||
2779 | sub-part of it to another constant, merge them by making a new | ||||||
2780 | constant. */ | ||||||
2781 | if (i1
| ||||||
2782 | && (temp_expr = single_set (i2)) != 0 | ||||||
2783 | && is_a <scalar_int_mode> (GET_MODE (SET_DEST (temp_expr))((machine_mode) ((((temp_expr)->u.fld[0]).rt_rtx))->mode ), &temp_mode) | ||||||
2784 | && CONST_SCALAR_INT_P (SET_SRC (temp_expr))((((enum rtx_code) ((((temp_expr)->u.fld[1]).rt_rtx))-> code) == CONST_INT) || (((enum rtx_code) ((((temp_expr)->u .fld[1]).rt_rtx))->code) == CONST_WIDE_INT)) | ||||||
2785 | && GET_CODE (PATTERN (i3))((enum rtx_code) (PATTERN (i3))->code) == SET | ||||||
2786 | && CONST_SCALAR_INT_P (SET_SRC (PATTERN (i3)))((((enum rtx_code) ((((PATTERN (i3))->u.fld[1]).rt_rtx))-> code) == CONST_INT) || (((enum rtx_code) ((((PATTERN (i3))-> u.fld[1]).rt_rtx))->code) == CONST_WIDE_INT)) | ||||||
2787 | && reg_subword_p (SET_DEST (PATTERN (i3))(((PATTERN (i3))->u.fld[0]).rt_rtx), SET_DEST (temp_expr)(((temp_expr)->u.fld[0]).rt_rtx))) | ||||||
2788 | { | ||||||
2789 | rtx dest = SET_DEST (PATTERN (i3))(((PATTERN (i3))->u.fld[0]).rt_rtx); | ||||||
2790 | rtx temp_dest = SET_DEST (temp_expr)(((temp_expr)->u.fld[0]).rt_rtx); | ||||||
2791 | int offset = -1; | ||||||
2792 | int width = 0; | ||||||
2793 | |||||||
2794 | if (GET_CODE (dest)((enum rtx_code) (dest)->code) == ZERO_EXTRACT) | ||||||
2795 | { | ||||||
2796 | if (CONST_INT_P (XEXP (dest, 1))(((enum rtx_code) ((((dest)->u.fld[1]).rt_rtx))->code) == CONST_INT) | ||||||
2797 | && CONST_INT_P (XEXP (dest, 2))(((enum rtx_code) ((((dest)->u.fld[2]).rt_rtx))->code) == CONST_INT) | ||||||
2798 | && is_a <scalar_int_mode> (GET_MODE (XEXP (dest, 0))((machine_mode) ((((dest)->u.fld[0]).rt_rtx))->mode), | ||||||
2799 | &dest_mode)) | ||||||
2800 | { | ||||||
2801 | width = INTVAL (XEXP (dest, 1))(((((dest)->u.fld[1]).rt_rtx))->u.hwint[0]); | ||||||
2802 | offset = INTVAL (XEXP (dest, 2))(((((dest)->u.fld[2]).rt_rtx))->u.hwint[0]); | ||||||
2803 | dest = XEXP (dest, 0)(((dest)->u.fld[0]).rt_rtx); | ||||||
2804 | if (BITS_BIG_ENDIAN0) | ||||||
2805 | offset = GET_MODE_PRECISION (dest_mode) - width - offset; | ||||||
2806 | } | ||||||
2807 | } | ||||||
2808 | else | ||||||
2809 | { | ||||||
2810 | if (GET_CODE (dest)((enum rtx_code) (dest)->code) == STRICT_LOW_PART) | ||||||
2811 | dest = XEXP (dest, 0)(((dest)->u.fld[0]).rt_rtx); | ||||||
2812 | if (is_a <scalar_int_mode> (GET_MODE (dest)((machine_mode) (dest)->mode), &dest_mode)) | ||||||
2813 | { | ||||||
2814 | width = GET_MODE_PRECISION (dest_mode); | ||||||
2815 | offset = 0; | ||||||
2816 | } | ||||||
2817 | } | ||||||
2818 | |||||||
2819 | if (offset >= 0) | ||||||
2820 | { | ||||||
2821 | /* If this is the low part, we're done. */ | ||||||
2822 | if (subreg_lowpart_p (dest)) | ||||||
2823 | ; | ||||||
2824 | /* Handle the case where inner is twice the size of outer. */ | ||||||
2825 | else if (GET_MODE_PRECISION (temp_mode) | ||||||
2826 | == 2 * GET_MODE_PRECISION (dest_mode)) | ||||||
2827 | offset += GET_MODE_PRECISION (dest_mode); | ||||||
2828 | /* Otherwise give up for now. */ | ||||||
2829 | else | ||||||
2830 | offset = -1; | ||||||
2831 | } | ||||||
2832 | |||||||
2833 | if (offset >= 0) | ||||||
2834 | { | ||||||
2835 | rtx inner = SET_SRC (PATTERN (i3))(((PATTERN (i3))->u.fld[1]).rt_rtx); | ||||||
2836 | rtx outer = SET_SRC (temp_expr)(((temp_expr)->u.fld[1]).rt_rtx); | ||||||
2837 | |||||||
2838 | wide_int o = wi::insert (rtx_mode_t (outer, temp_mode), | ||||||
2839 | rtx_mode_t (inner, dest_mode), | ||||||
2840 | offset, width); | ||||||
2841 | |||||||
2842 | combine_merges++; | ||||||
2843 | subst_insn = i3; | ||||||
2844 | subst_low_luid = DF_INSN_LUID (i2)((((df->insns[(INSN_UID (i2))]))->luid)); | ||||||
2845 | added_sets_2 = added_sets_1 = added_sets_0 = 0; | ||||||
2846 | i2dest = temp_dest; | ||||||
2847 | i2dest_killed = dead_or_set_p (i2, i2dest); | ||||||
2848 | |||||||
2849 | /* Replace the source in I2 with the new constant and make the | ||||||
2850 | resulting insn the new pattern for I3. Then skip to where we | ||||||
2851 | validate the pattern. Everything was set up above. */ | ||||||
2852 | SUBST (SET_SRC (temp_expr),do_SUBST (&((((temp_expr)->u.fld[1]).rt_rtx)), (immed_wide_int_const (o, temp_mode))) | ||||||
2853 | immed_wide_int_const (o, temp_mode))do_SUBST (&((((temp_expr)->u.fld[1]).rt_rtx)), (immed_wide_int_const (o, temp_mode))); | ||||||
2854 | |||||||
2855 | newpat = PATTERN (i2); | ||||||
2856 | |||||||
2857 | /* The dest of I3 has been replaced with the dest of I2. */ | ||||||
2858 | changed_i3_dest = 1; | ||||||
2859 | goto validate_replacement; | ||||||
2860 | } | ||||||
2861 | } | ||||||
2862 | |||||||
2863 | /* If we have no I1 and I2 looks like: | ||||||
2864 | (parallel [(set (reg:CC X) (compare:CC OP (const_int 0))) | ||||||
2865 | (set Y OP)]) | ||||||
2866 | make up a dummy I1 that is | ||||||
2867 | (set Y OP) | ||||||
2868 | and change I2 to be | ||||||
2869 | (set (reg:CC X) (compare:CC Y (const_int 0))) | ||||||
2870 | |||||||
2871 | (We can ignore any trailing CLOBBERs.) | ||||||
2872 | |||||||
2873 | This undoes a previous combination and allows us to match a branch-and- | ||||||
2874 | decrement insn. */ | ||||||
2875 | |||||||
2876 | if (i1
| ||||||
2877 | && is_parallel_of_n_reg_sets (PATTERN (i2), 2) | ||||||
2878 | && (GET_MODE_CLASS (GET_MODE (SET_DEST (XVECEXP (PATTERN (i2), 0, 0))))((enum mode_class) mode_class[((machine_mode) (((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[0]))->u.fld[0]).rt_rtx ))->mode)]) | ||||||
2879 | == MODE_CC) | ||||||
2880 | && GET_CODE (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)))((enum rtx_code) (((((((((PATTERN (i2))->u.fld[0]).rt_rtvec ))->elem[0]))->u.fld[1]).rt_rtx))->code) == COMPARE | ||||||
2881 | && XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 1)(((((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[0] ))->u.fld[1]).rt_rtx))->u.fld[1]).rt_rtx) == const0_rtx(const_int_rtx[64]) | ||||||
2882 | && rtx_equal_p (XEXP (SET_SRC (XVECEXP (PATTERN (i2), 0, 0)), 0)(((((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[0] ))->u.fld[1]).rt_rtx))->u.fld[0]).rt_rtx), | ||||||
2883 | SET_SRC (XVECEXP (PATTERN (i2), 0, 1))((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[1]))-> u.fld[1]).rt_rtx)) | ||||||
2884 | && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0))((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[0]))-> u.fld[0]).rt_rtx), i2, i3) | ||||||
2885 | && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 1))((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[1]))-> u.fld[0]).rt_rtx), i2, i3)) | ||||||
2886 | { | ||||||
2887 | /* We make I1 with the same INSN_UID as I2. This gives it | ||||||
2888 | the same DF_INSN_LUID for value tracking. Our fake I1 will | ||||||
2889 | never appear in the insn stream so giving it the same INSN_UID | ||||||
2890 | as I2 will not cause a problem. */ | ||||||
2891 | |||||||
2892 | i1 = gen_rtx_INSN (VOIDmode((void) 0, E_VOIDmode), NULLnullptr, i2, BLOCK_FOR_INSN (i2), | ||||||
2893 | XVECEXP (PATTERN (i2), 0, 1)(((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[1]), INSN_LOCATION (i2), | ||||||
2894 | -1, NULL_RTX(rtx) 0); | ||||||
2895 | INSN_UID (i1) = INSN_UID (i2); | ||||||
2896 | |||||||
2897 | SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 0))do_SUBST (&(PATTERN (i2)), ((((((PATTERN (i2))->u.fld[ 0]).rt_rtvec))->elem[0]))); | ||||||
2898 | SUBST (XEXP (SET_SRC (PATTERN (i2)), 0),do_SUBST (&(((((((PATTERN (i2))->u.fld[1]).rt_rtx))-> u.fld[0]).rt_rtx)), ((((PATTERN (i1))->u.fld[0]).rt_rtx))) | ||||||
2899 | SET_DEST (PATTERN (i1)))do_SUBST (&(((((((PATTERN (i2))->u.fld[1]).rt_rtx))-> u.fld[0]).rt_rtx)), ((((PATTERN (i1))->u.fld[0]).rt_rtx))); | ||||||
2900 | unsigned int regno = REGNO (SET_DEST (PATTERN (i1)))(rhs_regno((((PATTERN (i1))->u.fld[0]).rt_rtx))); | ||||||
2901 | SUBST_LINK (LOG_LINKS (i2),do_SUBST_LINK (&(uid_log_links[insn_uid_check (i2)]), alloc_insn_link (i1, regno, (uid_log_links[insn_uid_check (i2)]))) | ||||||
2902 | alloc_insn_link (i1, regno, LOG_LINKS (i2)))do_SUBST_LINK (&(uid_log_links[insn_uid_check (i2)]), alloc_insn_link (i1, regno, (uid_log_links[insn_uid_check (i2)]))); | ||||||
2903 | } | ||||||
2904 | |||||||
2905 | /* If I2 is a PARALLEL of two SETs of REGs (and perhaps some CLOBBERs), | ||||||
2906 | make those two SETs separate I1 and I2 insns, and make an I0 that is | ||||||
2907 | the original I1. */ | ||||||
2908 | if (i0
| ||||||
2909 | && is_parallel_of_n_reg_sets (PATTERN (i2), 2) | ||||||
2910 | && can_split_parallel_of_n_reg_sets (i2, 2) | ||||||
2911 | && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0))((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[0]))-> u.fld[0]).rt_rtx), i2, i3) | ||||||
2912 | && !reg_used_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 1))((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[1]))-> u.fld[0]).rt_rtx), i2, i3) | ||||||
2913 | && !reg_set_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 0))((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[0]))-> u.fld[0]).rt_rtx), i2, i3) | ||||||
2914 | && !reg_set_between_p (SET_DEST (XVECEXP (PATTERN (i2), 0, 1))((((((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[1]))-> u.fld[0]).rt_rtx), i2, i3)) | ||||||
2915 | { | ||||||
2916 | /* If there is no I1, there is no I0 either. */ | ||||||
2917 | i0 = i1; | ||||||
2918 | |||||||
2919 | /* We make I1 with the same INSN_UID as I2. This gives it | ||||||
2920 | the same DF_INSN_LUID for value tracking. Our fake I1 will | ||||||
2921 | never appear in the insn stream so giving it the same INSN_UID | ||||||
2922 | as I2 will not cause a problem. */ | ||||||
2923 | |||||||
2924 | i1 = gen_rtx_INSN (VOIDmode((void) 0, E_VOIDmode), NULLnullptr, i2, BLOCK_FOR_INSN (i2), | ||||||
2925 | XVECEXP (PATTERN (i2), 0, 0)(((((PATTERN (i2))->u.fld[0]).rt_rtvec))->elem[0]), INSN_LOCATION (i2), | ||||||
2926 | -1, NULL_RTX(rtx) 0); | ||||||
2927 | INSN_UID (i1) = INSN_UID (i2); | ||||||
2928 | |||||||
2929 | SUBST (PATTERN (i2), XVECEXP (PATTERN (i2), 0, 1))do_SUBST (&(PATTERN (i2)), ((((((PATTERN (i2))->u.fld[ 0]).rt_rtvec))->elem[1]))); | ||||||
2930 | } | ||||||
2931 | |||||||
2932 | /* Verify that I2 and maybe I1 and I0 can be combined into I3. */ | ||||||
2933 | if (!can_combine_p (i2, i3, i0, i1, NULLnullptr, NULLnullptr, &i2dest, &i2src)) | ||||||
2934 | { | ||||||
2935 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||||
2936 | fprintf (dump_file, "Can't combine i2 into i3\n"); | ||||||
2937 | undo_all (); | ||||||
2938 | return 0; | ||||||
2939 | } | ||||||
2940 | if (i1
| ||||||
2941 | { | ||||||
2942 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||||
2943 | fprintf (dump_file, "Can't combine i1 into i3\n"); | ||||||
2944 | undo_all (); | ||||||
2945 | return 0; | ||||||
2946 | } | ||||||
2947 | if (i0
| ||||||
2948 | { | ||||||
2949 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||||
2950 | fprintf (dump_file, "Can't combine i0 into i3\n"); | ||||||
2951 | undo_all (); | ||||||
2952 | return 0; | ||||||
2953 | } | ||||||
2954 | |||||||
2955 | /* With non-call exceptions we can end up trying to combine multiple | ||||||
2956 | insns with possible EH side effects. Make sure we can combine | ||||||
2957 | that to a single insn which means there must be at most one insn | ||||||
2958 | in the combination with an EH side effect. */ | ||||||
2959 | if (cfun(cfun + 0)->can_throw_non_call_exceptions) | ||||||
2960 | { | ||||||
2961 | if (find_reg_note (i3, REG_EH_REGION, NULL_RTX(rtx) 0) | ||||||
2962 | || find_reg_note (i2, REG_EH_REGION, NULL_RTX(rtx) 0) | ||||||
2963 | || (i1 && find_reg_note (i1, REG_EH_REGION, NULL_RTX(rtx) 0)) | ||||||
2964 | || (i0 && find_reg_note (i0, REG_EH_REGION, NULL_RTX(rtx) 0))) | ||||||
2965 | { | ||||||
2966 | has_non_call_exception = true; | ||||||
2967 | if (insn_could_throw_p (i3) | ||||||
2968 | + insn_could_throw_p (i2) | ||||||
2969 | + (i1 ? insn_could_throw_p (i1) : 0) | ||||||
2970 | + (i0 ? insn_could_throw_p (i0) : 0) > 1) | ||||||
2971 | { | ||||||
2972 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||||
2973 | fprintf (dump_file, "Can't combine multiple insns with EH " | ||||||
2974 | "side-effects\n"); | ||||||
2975 | undo_all (); | ||||||
2976 | return 0; | ||||||
2977 | } | ||||||
2978 | } | ||||||
2979 | } | ||||||
2980 | |||||||
2981 | /* Record whether i2 and i3 are trivial moves. */ | ||||||
2982 | i2_was_move = is_just_move (i2); | ||||||
2983 | i3_was_move = is_just_move (i3); | ||||||
2984 | |||||||
2985 | /* Record whether I2DEST is used in I2SRC and similarly for the other | ||||||
2986 | cases. Knowing this will help in register status updating below. */ | ||||||
2987 | i2dest_in_i2src = reg_overlap_mentioned_p (i2dest, i2src); | ||||||
2988 | i1dest_in_i1src = i1
| ||||||
2989 | i2dest_in_i1src = i1
| ||||||
2990 | i0dest_in_i0src = i0
| ||||||
2991 | i1dest_in_i0src = i0
| ||||||
2992 | i2dest_in_i0src = i0
| ||||||
2993 | i2dest_killed = dead_or_set_p (i2, i2dest); | ||||||
2994 | i1dest_killed = i1
| ||||||
2995 | i0dest_killed = i0
| ||||||
2996 | |||||||
2997 | /* For the earlier insns, determine which of the subsequent ones they | ||||||
2998 | feed. */ | ||||||
2999 | i1_feeds_i2_n = i1
| ||||||
3000 | i0_feeds_i1_n = i0
| ||||||
3001 | i0_feeds_i2_n = (i0
| ||||||
3002 | : (!reg_overlap_mentioned_p (i1dest, i0dest) | ||||||
3003 | && reg_overlap_mentioned_p (i0dest, i2src)))); | ||||||
3004 | |||||||
3005 | /* Ensure that I3's pattern can be the destination of combines. */ | ||||||
3006 | if (! combinable_i3pat (i3, &PATTERN (i3), i2dest, i1dest, i0dest, | ||||||
3007 | i1
| ||||||
3008 | i0
| ||||||
3009 | || (i1dest_in_i0src && !i0_feeds_i1_n)), | ||||||
3010 | &i3dest_killed)) | ||||||
3011 | { | ||||||
3012 | undo_all (); | ||||||
3013 | return 0; | ||||||
3014 | } | ||||||
3015 | |||||||
3016 | /* See if any of the insns is a MULT operation. Unless one is, we will | ||||||
3017 | reject a combination that is, since it must be slower. Be conservative | ||||||
3018 | here. */ | ||||||
3019 | if (GET_CODE (i2src)((enum rtx_code) (i2src)->code) == MULT | ||||||
3020 | || (i1
| ||||||
3021 | || (i0
| ||||||
3022 | || (GET_CODE (PATTERN (i3))((enum rtx_code) (PATTERN (i3))->code) == SET | ||||||
3023 | && GET_CODE (SET_SRC (PATTERN (i3)))((enum rtx_code) ((((PATTERN (i3))->u.fld[1]).rt_rtx))-> code) == MULT)) | ||||||
3024 | have_mult = 1; | ||||||
3025 | |||||||
3026 | /* If I3 has an inc, then give up if I1 or I2 uses the reg that is inc'd. | ||||||
3027 | We used to do this EXCEPT in one case: I3 has a post-inc in an | ||||||
3028 | output operand. However, that exception can give rise to insns like | ||||||
3029 | mov r3,(r3)+ | ||||||
3030 | which is a famous insn on the PDP-11 where the value of r3 used as the | ||||||
3031 | source was model-dependent. Avoid this sort of thing. */ | ||||||
3032 | |||||||
3033 | #if 0 | ||||||
3034 | if (!(GET_CODE (PATTERN (i3))((enum rtx_code) (PATTERN (i3))->code) == SET | ||||||
3035 | && REG_P (SET_SRC (PATTERN (i3)))(((enum rtx_code) ((((PATTERN (i3))->u.fld[1]).rt_rtx))-> code) == REG) | ||||||
3036 | && MEM_P (SET_DEST (PATTERN (i3)))(((enum rtx_code) ((((PATTERN (i3))->u.fld[0]).rt_rtx))-> code) == MEM) | ||||||
3037 | && (GET_CODE (XEXP (SET_DEST (PATTERN (i3)), 0))((enum rtx_code) (((((((PATTERN (i3))->u.fld[0]).rt_rtx))-> u.fld[0]).rt_rtx))->code) == POST_INC | ||||||
3038 | || GET_CODE (XEXP (SET_DEST (PATTERN (i3)), 0))((enum rtx_code) (((((((PATTERN (i3))->u.fld[0]).rt_rtx))-> u.fld[0]).rt_rtx))->code) == POST_DEC))) | ||||||
3039 | /* It's not the exception. */ | ||||||
3040 | #endif | ||||||
3041 | if (AUTO_INC_DEC0) | ||||||
3042 | { | ||||||
3043 | rtx link; | ||||||
3044 | for (link = REG_NOTES (i3)(((i3)->u.fld[6]).rt_rtx); link; link = XEXP (link, 1)(((link)->u.fld[1]).rt_rtx)) | ||||||
3045 | if (REG_NOTE_KIND (link)((enum reg_note) ((machine_mode) (link)->mode)) == REG_INC | ||||||
3046 | && (reg_overlap_mentioned_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), PATTERN (i2)) | ||||||
3047 | || (i1 != 0 | ||||||
3048 | && reg_overlap_mentioned_p (XEXP (link, 0)(((link)->u.fld[0]).rt_rtx), PATTERN (i1))))) | ||||||
3049 | { | ||||||
3050 | undo_all (); | ||||||
3051 | return 0; | ||||||
3052 | } | ||||||
3053 | } | ||||||
3054 | |||||||
3055 | /* See if the SETs in I1 or I2 need to be kept around in the merged | ||||||
3056 | instruction: whenever the value set there is still needed past I3. | ||||||
3057 | For the SET in I2, this is easy: we see if I2DEST dies or is set in I3. | ||||||
3058 | |||||||
3059 | For the SET in I1, we have two cases: if I1 and I2 independently feed | ||||||
3060 | into I3, the set in I1 needs to be kept around unless I1DEST dies | ||||||
3061 | or is set in I3. Otherwise (if I1 feeds I2 which feeds I3), the set | ||||||
3062 | in I1 needs to be kept around unless I1DEST dies or is set in either | ||||||
3063 | I2 or I3. The same considerations apply to I0. */ | ||||||
3064 | |||||||
3065 | added_sets_2 = !dead_or_set_p (i3, i2dest); | ||||||
3066 | |||||||
3067 | if (i1
| ||||||
3068 | added_sets_1 = !(dead_or_set_p (i3, i1dest) | ||||||
3069 | || (i1_feeds_i2_n && dead_or_set_p (i2, i1dest))); | ||||||
3070 | else | ||||||
3071 | added_sets_1 = 0; | ||||||
3072 | |||||||
3073 | if (i0
| ||||||
3074 | added_sets_0 = !(dead_or_set_p (i3, i0dest) | ||||||
3075 | || (i0_feeds_i1_n && dead_or_set_p (i1, i0dest)) | ||||||
3076 | || ((i0_feeds_i2_n || (i0_feeds_i1_n && i1_feeds_i2_n)) | ||||||
3077 | && dead_or_set_p (i2, i0dest))); | ||||||
3078 | else | ||||||
3079 | added_sets_0 = 0; | ||||||
3080 | |||||||
3081 | /* We are about to copy insns for the case where they need to be kept | ||||||
3082 | around. Check that they can be copied in the merged instruction. */ | ||||||
3083 | |||||||
3084 | if (targetm.cannot_copy_insn_p | ||||||
3085 | && ((added_sets_2 && targetm.cannot_copy_insn_p (i2)) | ||||||
3086 | || (i1 && added_sets_1 && targetm.cannot_copy_insn_p (i1)) | ||||||
3087 | || (i0 && added_sets_0 && targetm.cannot_copy_insn_p (i0)))) | ||||||
3088 | { | ||||||
3089 | undo_all (); | ||||||
3090 | return 0; | ||||||
3091 | } | ||||||
3092 | |||||||
3093 | /* We cannot safely duplicate volatile references in any case. */ | ||||||
3094 | |||||||
3095 | if ((added_sets_2
| ||||||
3096 | || (added_sets_1
| ||||||
3097 | || (added_sets_0
| ||||||
3098 | { | ||||||
3099 | undo_all (); | ||||||
3100 | return 0; | ||||||
3101 | } | ||||||
3102 | |||||||
3103 | /* Count how many auto_inc expressions there were in the original insns; | ||||||
3104 | we need to have the same number in the resulting patterns. */ | ||||||
3105 | |||||||
3106 | if (i0
| ||||||
3107 | for_each_inc_dec (PATTERN (i0), count_auto_inc, &n_auto_inc); | ||||||
3108 | if (i1
| ||||||
3109 | for_each_inc_dec (PATTERN (i1), count_auto_inc, &n_auto_inc); | ||||||
3110 | for_each_inc_dec (PATTERN (i2), count_auto_inc, &n_auto_inc); | ||||||
3111 | for_each_inc_dec (PATTERN (i3), count_auto_inc, &n_auto_inc); | ||||||
3112 | |||||||
3113 | /* If the set in I2 needs to be kept around, we must make a copy of | ||||||
3114 | PATTERN (I2), so that when we substitute I1SRC for I1DEST in | ||||||
3115 | PATTERN (I2), we are only substituting for the original I1DEST, not into | ||||||
3116 | an already-substituted copy. This also prevents making self-referential | ||||||
3117 | rtx. If I2 is a PARALLEL, we just need the piece that assigns I2SRC to | ||||||
3118 | I2DEST. */ | ||||||
3119 | |||||||
3120 | if (added_sets_2
| ||||||
3121 | { | ||||||
3122 | if (GET_CODE (PATTERN (i2))((enum rtx_code) (PATTERN (i2))->code) == PARALLEL) | ||||||
3123 | i2pat = gen_rtx_SET (i2dest, copy_rtx (i2src))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((i2dest )), ((copy_rtx (i2src))) ); | ||||||
3124 | else | ||||||
3125 | i2pat = copy_rtx (PATTERN (i2)); | ||||||
3126 | } | ||||||
3127 | |||||||
3128 | if (added_sets_1
| ||||||
3129 | { | ||||||
3130 | if (GET_CODE (PATTERN (i1))((enum rtx_code) (PATTERN (i1))->code) == PARALLEL) | ||||||
3131 | i1pat = gen_rtx_SET (i1dest, copy_rtx (i1src))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((i1dest )), ((copy_rtx (i1src))) ); | ||||||
3132 | else | ||||||
3133 | i1pat = copy_rtx (PATTERN (i1)); | ||||||
3134 | } | ||||||
3135 | |||||||
3136 | if (added_sets_0
| ||||||
3137 | { | ||||||
3138 | if (GET_CODE (PATTERN (i0))((enum rtx_code) (PATTERN (i0))->code) == PARALLEL) | ||||||
3139 | i0pat = gen_rtx_SET (i0dest, copy_rtx (i0src))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((i0dest )), ((copy_rtx (i0src))) ); | ||||||
3140 | else | ||||||
3141 | i0pat = copy_rtx (PATTERN (i0)); | ||||||
3142 | } | ||||||
3143 | |||||||
3144 | combine_merges++; | ||||||
3145 | |||||||
3146 | /* Substitute in the latest insn for the regs set by the earlier ones. */ | ||||||
3147 | |||||||
3148 | maxreg = max_reg_num (); | ||||||
3149 | |||||||
3150 | subst_insn = i3; | ||||||
3151 | |||||||
3152 | /* Many machines have insns that can both perform an | ||||||
3153 | arithmetic operation and set the condition code. These operations will | ||||||
3154 | be represented as a PARALLEL with the first element of the vector | ||||||
3155 | being a COMPARE of an arithmetic operation with the constant zero. | ||||||
3156 | The second element of the vector will set some pseudo to the result | ||||||
3157 | of the same arithmetic operation. If we simplify the COMPARE, we won't | ||||||
3158 | match such a pattern and so will generate an extra insn. Here we test | ||||||
3159 | for this case, where both the comparison and the operation result are | ||||||
3160 | needed, and make the PARALLEL by just replacing I2DEST in I3SRC with | ||||||
3161 | I2SRC. Later we will make the PARALLEL that contains I2. */ | ||||||
3162 | |||||||
3163 | if (i1
| ||||||
3164 | && GET_CODE (SET_SRC (PATTERN (i3)))((enum rtx_code) ((((PATTERN (i3))->u.fld[1]).rt_rtx))-> code) == COMPARE | ||||||
3165 | && CONST_INT_P (XEXP (SET_SRC (PATTERN (i3)), 1))(((enum rtx_code) (((((((PATTERN (i3))->u.fld[1]).rt_rtx)) ->u.fld[1]).rt_rtx))->code) == CONST_INT) | ||||||
3166 | && rtx_equal_p (XEXP (SET_SRC (PATTERN (i3)), 0)((((((PATTERN (i3))->u.fld[1]).rt_rtx))->u.fld[0]).rt_rtx ), i2dest)) | ||||||
3167 | { | ||||||
3168 | rtx newpat_dest; | ||||||
3169 | rtx *cc_use_loc = NULLnullptr; | ||||||
3170 | rtx_insn *cc_use_insn = NULLnullptr; | ||||||
3171 | rtx op0 = i2src, op1 = XEXP (SET_SRC (PATTERN (i3)), 1)((((((PATTERN (i3))->u.fld[1]).rt_rtx))->u.fld[1]).rt_rtx ); | ||||||
3172 | machine_mode compare_mode, orig_compare_mode; | ||||||
3173 | enum rtx_code compare_code = UNKNOWN, orig_compare_code = UNKNOWN; | ||||||
3174 | scalar_int_mode mode; | ||||||
3175 | |||||||
3176 | newpat = PATTERN (i3); | ||||||
3177 | newpat_dest = SET_DEST (newpat)(((newpat)->u.fld[0]).rt_rtx); | ||||||
3178 | compare_mode = orig_compare_mode = GET_MODE (newpat_dest)((machine_mode) (newpat_dest)->mode); | ||||||
3179 | |||||||
3180 | if (undobuf.other_insn == 0 | ||||||
3181 | && (cc_use_loc = find_single_use (SET_DEST (newpat)(((newpat)->u.fld[0]).rt_rtx), i3, | ||||||
3182 | &cc_use_insn))) | ||||||
3183 | { | ||||||
3184 | compare_code = orig_compare_code = GET_CODE (*cc_use_loc)((enum rtx_code) (*cc_use_loc)->code); | ||||||
3185 | if (is_a <scalar_int_mode> (GET_MODE (i2dest)((machine_mode) (i2dest)->mode), &mode)) | ||||||
3186 | compare_code = simplify_compare_const (compare_code, mode, | ||||||
3187 | op0, &op1); | ||||||
3188 | target_canonicalize_comparison (&compare_code, &op0, &op1, 1); | ||||||
3189 | } | ||||||
3190 | |||||||
3191 | /* Do the rest only if op1 is const0_rtx, which may be the | ||||||
3192 | result of simplification. */ | ||||||
3193 | if (op1 == const0_rtx(const_int_rtx[64])) | ||||||
3194 | { | ||||||
3195 | /* If a single use of the CC is found, prepare to modify it | ||||||
3196 | when SELECT_CC_MODE returns a new CC-class mode, or when | ||||||
3197 | the above simplify_compare_const() returned a new comparison | ||||||
3198 | operator. undobuf.other_insn is assigned the CC use insn | ||||||
3199 | when modifying it. */ | ||||||
3200 | if (cc_use_loc) | ||||||
3201 | { | ||||||
3202 | #ifdef SELECT_CC_MODE | ||||||
3203 | machine_mode new_mode | ||||||
3204 | = SELECT_CC_MODE (compare_code, op0, op1)ix86_cc_mode ((compare_code), (op0), (op1)); | ||||||
3205 | if (new_mode != orig_compare_mode | ||||||
3206 | && can_change_dest_mode (SET_DEST (newpat)(((newpat)->u.fld[0]).rt_rtx), | ||||||
3207 | added_sets_2, new_mode)) | ||||||
3208 | { | ||||||
3209 | unsigned int regno = REGNO (newpat_dest)(rhs_regno(newpat_dest)); | ||||||
3210 | compare_mode = new_mode; | ||||||
3211 | if (regno < FIRST_PSEUDO_REGISTER76) | ||||||
3212 | newpat_dest = gen_rtx_REG (compare_mode, regno); | ||||||
3213 | else | ||||||
3214 | { | ||||||
3215 | subst_mode (regno, compare_mode); | ||||||
3216 | newpat_dest = regno_reg_rtx[regno]; | ||||||
3217 | } | ||||||
3218 | } | ||||||
3219 | #endif | ||||||
3220 | /* Cases for modifying the CC-using comparison. */ | ||||||
3221 | if (compare_code != orig_compare_code | ||||||
3222 | /* ??? Do we need to verify the zero rtx? */ | ||||||
3223 | && XEXP (*cc_use_loc, 1)(((*cc_use_loc)->u.fld[1]).rt_rtx) == const0_rtx(const_int_rtx[64])) | ||||||
3224 | { | ||||||
3225 | /* Replace cc_use_loc with entire new RTX. */ | ||||||
3226 | SUBST (*cc_use_loc,do_SUBST (&(*cc_use_loc), (gen_rtx_fmt_ee_stat ((compare_code ), (((machine_mode) (*cc_use_loc)->mode)), (newpat_dest), ( (const_int_rtx[64])) ))) | ||||||
3227 | gen_rtx_fmt_ee (compare_code, GET_MODE (*cc_use_loc),do_SUBST (&(*cc_use_loc), (gen_rtx_fmt_ee_stat ((compare_code ), (((machine_mode) (*cc_use_loc)->mode)), (newpat_dest), ( (const_int_rtx[64])) ))) | ||||||
3228 | newpat_dest, const0_rtx))do_SUBST (&(*cc_use_loc), (gen_rtx_fmt_ee_stat ((compare_code ), (((machine_mode) (*cc_use_loc)->mode)), (newpat_dest), ( (const_int_rtx[64])) ))); | ||||||
3229 | undobuf.other_insn = cc_use_insn; | ||||||
3230 | } | ||||||
3231 | else if (compare_mode != orig_compare_mode) | ||||||
3232 | { | ||||||
3233 | /* Just replace the CC reg with a new mode. */ | ||||||
3234 | SUBST (XEXP (*cc_use_loc, 0), newpat_dest)do_SUBST (&((((*cc_use_loc)->u.fld[0]).rt_rtx)), (newpat_dest )); | ||||||
3235 | undobuf.other_insn = cc_use_insn; | ||||||
3236 | } | ||||||
3237 | } | ||||||
3238 | |||||||
3239 | /* Now we modify the current newpat: | ||||||
3240 | First, SET_DEST(newpat) is updated if the CC mode has been | ||||||
3241 | altered. For targets without SELECT_CC_MODE, this should be | ||||||
3242 | optimized away. */ | ||||||
3243 | if (compare_mode != orig_compare_mode) | ||||||
3244 | SUBST (SET_DEST (newpat), newpat_dest)do_SUBST (&((((newpat)->u.fld[0]).rt_rtx)), (newpat_dest )); | ||||||
3245 | /* This is always done to propagate i2src into newpat. */ | ||||||
3246 | SUBST (SET_SRC (newpat),do_SUBST (&((((newpat)->u.fld[1]).rt_rtx)), (gen_rtx_fmt_ee_stat ((COMPARE), ((compare_mode)), ((op0)), ((op1)) ))) | ||||||
3247 | gen_rtx_COMPARE (compare_mode, op0, op1))do_SUBST (&((((newpat)->u.fld[1]).rt_rtx)), (gen_rtx_fmt_ee_stat ((COMPARE), ((compare_mode)), ((op0)), ((op1)) ))); | ||||||
3248 | /* Create new version of i2pat if needed; the below PARALLEL | ||||||
3249 | creation needs this to work correctly. */ | ||||||
3250 | if (! rtx_equal_p (i2src, op0)) | ||||||
3251 | i2pat = gen_rtx_SET (i2dest, op0)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((i2dest )), ((op0)) ); | ||||||
3252 | i2_is_used = 1; | ||||||
3253 | } | ||||||
3254 | } | ||||||
3255 | |||||||
3256 | if (i2_is_used
| ||||||
3257 | { | ||||||
3258 | /* It is possible that the source of I2 or I1 may be performing | ||||||
3259 | an unneeded operation, such as a ZERO_EXTEND of something | ||||||
3260 | that is known to have the high part zero. Handle that case | ||||||
3261 | by letting subst look at the inner insns. | ||||||
3262 | |||||||
3263 | Another way to do this would be to have a function that tries | ||||||
3264 | to simplify a single insn instead of merging two or more | ||||||
3265 | insns. We don't do this because of the potential of infinite | ||||||
3266 | loops and because of the potential extra memory required. | ||||||
3267 | However, doing it the way we are is a bit of a kludge and | ||||||
3268 | doesn't catch all cases. | ||||||
3269 | |||||||
3270 | But only do this if -fexpensive-optimizations since it slows | ||||||
3271 | things down and doesn't usually win. | ||||||
3272 | |||||||
3273 | This is not done in the COMPARE case above because the | ||||||
3274 | unmodified I2PAT is used in the PARALLEL and so a pattern | ||||||
3275 | with a modified I2SRC would not match. */ | ||||||
3276 | |||||||
3277 | if (flag_expensive_optimizationsglobal_options.x_flag_expensive_optimizations) | ||||||
3278 | { | ||||||
3279 | /* Pass pc_rtx so no substitutions are done, just | ||||||
3280 | simplifications. */ | ||||||
3281 | if (i1) | ||||||
3282 | { | ||||||
3283 | subst_low_luid = DF_INSN_LUID (i1)((((df->insns[(INSN_UID (i1))]))->luid)); | ||||||
3284 | i1src = subst (i1src, pc_rtx, pc_rtx, 0, 0, 0); | ||||||
3285 | } | ||||||
3286 | |||||||
3287 | subst_low_luid = DF_INSN_LUID (i2)((((df->insns[(INSN_UID (i2))]))->luid)); | ||||||
3288 | i2src = subst (i2src, pc_rtx, pc_rtx, 0, 0, 0); | ||||||
3289 | } | ||||||
3290 | |||||||
3291 | n_occurrences = 0; /* `subst' counts here */ | ||||||
3292 | subst_low_luid = DF_INSN_LUID (i2)((((df->insns[(INSN_UID (i2))]))->luid)); | ||||||
3293 | |||||||
3294 | /* If I1 feeds into I2 and I1DEST is in I1SRC, we need to make a unique | ||||||
3295 | copy of I2SRC each time we substitute it, in order to avoid creating | ||||||
3296 | self-referential RTL when we will be substituting I1SRC for I1DEST | ||||||
3297 | later. Likewise if I0 feeds into I2, either directly or indirectly | ||||||
3298 | through I1, and I0DEST is in I0SRC. */ | ||||||
3299 | newpat = subst (PATTERN (i3), i2dest, i2src, 0, 0, | ||||||
3300 | (i1_feeds_i2_n
| ||||||
3301 | || ((i0_feeds_i2_n
| ||||||
3302 | && i0dest_in_i0src)); | ||||||
3303 | substed_i2 = 1; | ||||||
3304 | |||||||
3305 | /* Record whether I2's body now appears within I3's body. */ | ||||||
3306 | i2_is_used = n_occurrences; | ||||||
3307 | } | ||||||
3308 | |||||||
3309 | /* If we already got a failure, don't try to do more. Otherwise, try to | ||||||
3310 | substitute I1 if we have it. */ | ||||||
3311 | |||||||
3312 | if (i1
| ||||||
3313 | { | ||||||
3314 | /* Before we can do this substitution, we must redo the test done | ||||||
3315 | above (see detailed comments there) that ensures I1DEST isn't | ||||||
3316 | mentioned in any SETs in NEWPAT that are field assignments. */ | ||||||
3317 | if (!combinable_i3pat (NULLnullptr, &newpat, i1dest, NULL_RTX(rtx) 0, NULL_RTX(rtx) 0, | ||||||
3318 | 0, 0, 0)) | ||||||
3319 | { | ||||||
3320 | undo_all (); | ||||||
3321 | return 0; | ||||||
3322 | } | ||||||
3323 | |||||||
3324 | n_occurrences = 0; | ||||||
3325 | subst_low_luid = DF_INSN_LUID (i1)((((df->insns[(INSN_UID (i1))]))->luid)); | ||||||
3326 | |||||||
3327 | /* If the following substitution will modify I1SRC, make a copy of it | ||||||
3328 | for the case where it is substituted for I1DEST in I2PAT later. */ | ||||||
3329 | if (added_sets_2 && i1_feeds_i2_n) | ||||||
3330 | i1src_copy = copy_rtx (i1src); | ||||||
3331 | |||||||
3332 | /* If I0 feeds into I1 and I0DEST is in I0SRC, we need to make a unique | ||||||
3333 | copy of I1SRC each time we substitute it, in order to avoid creating | ||||||
3334 | self-referential RTL when we will be substituting I0SRC for I0DEST | ||||||
3335 | later. */ | ||||||
3336 | newpat = subst (newpat, i1dest, i1src, 0, 0, | ||||||
3337 | i0_feeds_i1_n && i0dest_in_i0src); | ||||||
3338 | substed_i1 = 1; | ||||||
3339 | |||||||
3340 | /* Record whether I1's body now appears within I3's body. */ | ||||||
3341 | i1_is_used = n_occurrences; | ||||||
3342 | } | ||||||
3343 | |||||||
3344 | /* Likewise for I0 if we have it. */ | ||||||
3345 | |||||||
3346 | if (i0
| ||||||
3347 | { | ||||||
3348 | if (!combinable_i3pat (NULLnullptr, &newpat, i0dest, NULL_RTX(rtx) 0, NULL_RTX(rtx) 0, | ||||||
3349 | 0, 0, 0)) | ||||||
3350 | { | ||||||
3351 | undo_all (); | ||||||
3352 | return 0; | ||||||
3353 | } | ||||||
3354 | |||||||
3355 | /* If the following substitution will modify I0SRC, make a copy of it | ||||||
3356 | for the case where it is substituted for I0DEST in I1PAT later. */ | ||||||
3357 | if (added_sets_1 && i0_feeds_i1_n) | ||||||
3358 | i0src_copy = copy_rtx (i0src); | ||||||
3359 | /* And a copy for I0DEST in I2PAT substitution. */ | ||||||
3360 | if (added_sets_2 && ((i0_feeds_i1_n && i1_feeds_i2_n) | ||||||
3361 | || (i0_feeds_i2_n))) | ||||||
3362 | i0src_copy2 = copy_rtx (i0src); | ||||||
3363 | |||||||
3364 | n_occurrences = 0; | ||||||
3365 | subst_low_luid = DF_INSN_LUID (i0)((((df->insns[(INSN_UID (i0))]))->luid)); | ||||||
3366 | newpat = subst (newpat, i0dest, i0src, 0, 0, 0); | ||||||
3367 | substed_i0 = 1; | ||||||
3368 | } | ||||||
3369 | |||||||
3370 | if (n_auto_inc) | ||||||
3371 | { | ||||||
3372 | int new_n_auto_inc = 0; | ||||||
3373 | for_each_inc_dec (newpat, count_auto_inc, &new_n_auto_inc); | ||||||
3374 | |||||||
3375 | if (n_auto_inc != new_n_auto_inc) | ||||||
3376 | { | ||||||
3377 | if (dump_file && (dump_flags & TDF_DETAILS)) | ||||||
3378 | fprintf (dump_file, "Number of auto_inc expressions changed\n"); | ||||||
3379 | undo_all (); | ||||||
3380 | return 0; | ||||||
3381 | } | ||||||
3382 | } | ||||||
3383 | |||||||
3384 | /* Fail if an autoincrement side-effect has been duplicated. Be careful | ||||||
3385 | to count all the ways that I2SRC and I1SRC can be used. */ | ||||||
3386 | if ((FIND_REG_INC_NOTE (i2, NULL_RTX)0 != 0 | ||||||
3387 | && i2_is_used + added_sets_2 > 1) | ||||||
3388 | || (i1
| ||||||
3389 | && (i1_is_used + added_sets_1 + (added_sets_2 && i1_feeds_i2_n) | ||||||
3390 | > 1)) | ||||||
3391 | || (i0
| ||||||
3392 | && (n_occurrences + added_sets_0 | ||||||
3393 | + (added_sets_1 && i0_feeds_i1_n) | ||||||
3394 | + (added_sets_2 && i0_feeds_i2_n) | ||||||
3395 | > 1)) | ||||||
3396 | /* Fail if we tried to make a new register. */ | ||||||
3397 | || max_reg_num () != maxreg | ||||||
3398 | /* Fail if we couldn't do something and have a CLOBBER. */ | ||||||
3399 | || GET_CODE (newpat)((enum rtx_code) (newpat)->code) == CLOBBER | ||||||
3400 | /* Fail if this new pattern is a MULT and we didn't have one before | ||||||
3401 | at the outer level. */ | ||||||
3402 | || (GET_CODE (newpat)((enum rtx_code) (newpat)->code) == SET && GET_CODE (SET_SRC (newpat))((enum rtx_code) ((((newpat)->u.fld[1]).rt_rtx))->code) == MULT | ||||||
3403 | && ! have_mult)) | ||||||
3404 | { | ||||||
3405 | undo_all (); | ||||||
3406 | return 0; | ||||||
3407 | } | ||||||
3408 | |||||||
3409 | /* If the actions of the earlier insns must be kept | ||||||
3410 | in addition to substituting them into the latest one, | ||||||
3411 | we must make a new PARALLEL for the latest insn | ||||||
3412 | to hold additional the SETs. */ | ||||||
3413 | |||||||
3414 | if (added_sets_0
| ||||||
3415 | { | ||||||
3416 | int extra_sets = added_sets_0 + added_sets_1 + added_sets_2; | ||||||
3417 | combine_extras++; | ||||||
3418 | |||||||
3419 | if (GET_CODE (newpat)((enum rtx_code) (newpat)->code) == PARALLEL) | ||||||
3420 | { | ||||||
3421 | rtvec old = XVEC (newpat, 0)(((newpat)->u.fld[0]).rt_rtvec); | ||||||
3422 | total_sets = XVECLEN (newpat, 0)(((((newpat)->u.fld[0]).rt_rtvec))->num_elem) + extra_sets; | ||||||
3423 | newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (rtvec_alloc (total_sets))) ); | ||||||
3424 | memcpy (XVEC (newpat, 0)(((newpat)->u.fld[0]).rt_rtvec)->elem, &old->elem[0], | ||||||
3425 | sizeof (old->elem[0]) * old->num_elem); | ||||||
3426 | } | ||||||
3427 | else | ||||||
3428 | { | ||||||
3429 | rtx old = newpat; | ||||||
3430 | total_sets = 1 + extra_sets; | ||||||
3431 | newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_sets))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (rtvec_alloc (total_sets))) ); | ||||||
3432 | XVECEXP (newpat, 0, 0)(((((newpat)->u.fld[0]).rt_rtvec))->elem[0]) = old; | ||||||
3433 | } | ||||||
3434 | |||||||
3435 | if (added_sets_0) | ||||||
3436 | XVECEXP (newpat, 0, --total_sets)(((((newpat)->u.fld[0]).rt_rtvec))->elem[--total_sets]) = i0pat; | ||||||
3437 | |||||||
3438 | if (added_sets_1) | ||||||
3439 | { | ||||||
3440 | rtx t = i1pat; | ||||||
3441 | if (i0_feeds_i1_n) | ||||||
3442 | t = subst (t, i0dest, i0src_copy ? i0src_copy : i0src, 0, 0, 0); | ||||||
3443 | |||||||
3444 | XVECEXP (newpat, 0, --total_sets)(((((newpat)->u.fld[0]).rt_rtvec))->elem[--total_sets]) = t; | ||||||
3445 | } | ||||||
3446 | if (added_sets_2) | ||||||
3447 | { | ||||||
3448 | rtx t = i2pat; | ||||||
3449 | if (i1_feeds_i2_n) | ||||||
3450 | t = subst (t, i1dest, i1src_copy ? i1src_copy : i1src, 0, 0, | ||||||
3451 | i0_feeds_i1_n && i0dest_in_i0src); | ||||||
3452 | if ((i0_feeds_i1_n && i1_feeds_i2_n) || i0_feeds_i2_n) | ||||||
3453 | t = subst (t, i0dest, i0src_copy2 ? i0src_copy2 : i0src, 0, 0, 0); | ||||||
3454 | |||||||
3455 | XVECEXP (newpat, 0, --total_sets)(((((newpat)->u.fld[0]).rt_rtvec))->elem[--total_sets]) = t; | ||||||
3456 | } | ||||||
3457 | } | ||||||
3458 | |||||||
3459 | validate_replacement: | ||||||
3460 | |||||||
3461 | /* Note which hard regs this insn has as inputs. */ | ||||||
3462 | mark_used_regs_combine (newpat); | ||||||
3463 | |||||||
3464 | /* If recog_for_combine fails, it strips existing clobbers. If we'll | ||||||
3465 | consider splitting this pattern, we might need these clobbers. */ | ||||||
3466 | if (i1
| ||||||
3467 | && GET_CODE (XVECEXP (newpat, 0, XVECLEN (newpat, 0) - 1))((enum rtx_code) ((((((newpat)->u.fld[0]).rt_rtvec))->elem [(((((newpat)->u.fld[0]).rt_rtvec))->num_elem) - 1]))-> code) == CLOBBER) | ||||||
3468 | { | ||||||
3469 | int len = XVECLEN (newpat, 0)(((((newpat)->u.fld[0]).rt_rtvec))->num_elem); | ||||||
3470 | |||||||
3471 | newpat_vec_with_clobbers = rtvec_alloc (len); | ||||||
3472 | for (i = 0; i < len; i++) | ||||||
3473 | RTVEC_ELT (newpat_vec_with_clobbers, i)((newpat_vec_with_clobbers)->elem[i]) = XVECEXP (newpat, 0, i)(((((newpat)->u.fld[0]).rt_rtvec))->elem[i]); | ||||||
3474 | } | ||||||
3475 | |||||||
3476 | /* We have recognized nothing yet. */ | ||||||
3477 | insn_code_number = -1; | ||||||
3478 | |||||||
3479 | /* See if this is a PARALLEL of two SETs where one SET's destination is | ||||||
3480 | a register that is unused and this isn't marked as an instruction that | ||||||
3481 | might trap in an EH region. In that case, we just need the other SET. | ||||||
3482 | We prefer this over the PARALLEL. | ||||||
3483 | |||||||
3484 | This can occur when simplifying a divmod insn. We *must* test for this | ||||||
3485 | case here because the code below that splits two independent SETs doesn't | ||||||
3486 | handle this case correctly when it updates the register status. | ||||||
3487 | |||||||
3488 | It's pointless doing this if we originally had two sets, one from | ||||||
3489 | i3, and one from i2. Combining then splitting the parallel results | ||||||
3490 | in the original i2 again plus an invalid insn (which we delete). | ||||||
3491 | The net effect is only to move instructions around, which makes | ||||||
3492 | debug info less accurate. | ||||||
3493 | |||||||
3494 | If the remaining SET came from I2 its destination should not be used | ||||||
3495 | between I2 and I3. See PR82024. */ | ||||||
3496 | |||||||
3497 | if (!(added_sets_2
| ||||||
3498 | && is_parallel_of_n_reg_sets (newpat, 2) | ||||||
3499 | && asm_noperands (newpat) < 0) | ||||||
3500 | { | ||||||
3501 | rtx set0 = XVECEXP (newpat, 0, 0)(((((newpat)->u.fld[0]).rt_rtvec))->elem[0]); | ||||||
3502 | rtx set1 = XVECEXP (newpat, 0, 1)(((((newpat)->u.fld[0]).rt_rtvec))->elem[1]); | ||||||
3503 | rtx oldpat = newpat; | ||||||
3504 | |||||||
3505 | if (((REG_P (SET_DEST (set1))(((enum rtx_code) ((((set1)->u.fld[0]).rt_rtx))->code) == REG) | ||||||
3506 | && find_reg_note (i3, REG_UNUSED, SET_DEST (set1)(((set1)->u.fld[0]).rt_rtx))) | ||||||
3507 | || (GET_CODE (SET_DEST (set1))((enum rtx_code) ((((set1)->u.fld[0]).rt_rtx))->code) == SUBREG | ||||||
3508 | && find_reg_note (i3, REG_UNUSED, SUBREG_REG (SET_DEST (set1))((((((set1)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx)))) | ||||||
3509 | && insn_nothrow_p (i3) | ||||||
3510 | && !side_effects_p (SET_SRC (set1)(((set1)->u.fld[1]).rt_rtx))) | ||||||
3511 | { | ||||||
3512 | newpat = set0; | ||||||
3513 | insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); | ||||||
3514 | } | ||||||
3515 | |||||||
3516 | else if (((REG_P (SET_DEST (set0))(((enum rtx_code) ((((set0)->u.fld[0]).rt_rtx))->code) == REG) | ||||||
3517 | && find_reg_note (i3, REG_UNUSED, SET_DEST (set0)(((set0)->u.fld[0]).rt_rtx))) | ||||||
3518 | || (GET_CODE (SET_DEST (set0))((enum rtx_code) ((((set0)->u.fld[0]).rt_rtx))->code) == SUBREG | ||||||
3519 | && find_reg_note (i3, REG_UNUSED, | ||||||
3520 | SUBREG_REG (SET_DEST (set0))((((((set0)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx)))) | ||||||
3521 | && insn_nothrow_p (i3) | ||||||
3522 | && !side_effects_p (SET_SRC (set0)(((set0)->u.fld[1]).rt_rtx))) | ||||||
3523 | { | ||||||
3524 | rtx dest = SET_DEST (set1)(((set1)->u.fld[0]).rt_rtx); | ||||||
3525 | if (GET_CODE (dest)((enum rtx_code) (dest)->code) == SUBREG) | ||||||
3526 | dest = SUBREG_REG (dest)(((dest)->u.fld[0]).rt_rtx); | ||||||
3527 | if (!reg_used_between_p (dest, i2, i3)) | ||||||
3528 | { | ||||||
3529 | newpat = set1; | ||||||
3530 | insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); | ||||||
3531 | |||||||
3532 | if (insn_code_number >= 0) | ||||||
3533 | changed_i3_dest = 1; | ||||||
3534 | } | ||||||
3535 | } | ||||||
3536 | |||||||
3537 | if (insn_code_number < 0) | ||||||
3538 | newpat = oldpat; | ||||||
3539 | } | ||||||
3540 | |||||||
3541 | /* Is the result of combination a valid instruction? */ | ||||||
3542 | if (insn_code_number
| ||||||
3543 | insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); | ||||||
3544 | |||||||
3545 | /* If we were combining three insns and the result is a simple SET | ||||||
3546 | with no ASM_OPERANDS that wasn't recognized, try to split it into two | ||||||
3547 | insns. There are two ways to do this. It can be split using a | ||||||
3548 | machine-specific method (like when you have an addition of a large | ||||||
3549 | constant) or by combine in the function find_split_point. */ | ||||||
3550 | |||||||
3551 | if (i1
| ||||||
3552 | && asm_noperands (newpat) < 0) | ||||||
3553 | { | ||||||
3554 | rtx parallel, *split; | ||||||
3555 | rtx_insn *m_split_insn; | ||||||
3556 | |||||||
3557 | /* See if the MD file can split NEWPAT. If it can't, see if letting it | ||||||
3558 | use I2DEST as a scratch register will help. In the latter case, | ||||||
3559 | convert I2DEST to the mode of the source of NEWPAT if we can. */ | ||||||
3560 | |||||||
3561 | m_split_insn = combine_split_insns (newpat, i3); | ||||||
3562 | |||||||
3563 | /* We can only use I2DEST as a scratch reg if it doesn't overlap any | ||||||
3564 | inputs of NEWPAT. */ | ||||||
3565 | |||||||
3566 | /* ??? If I2DEST is not safe, and I1DEST exists, then it would be | ||||||
3567 | possible to try that as a scratch reg. This would require adding | ||||||
3568 | more code to make it work though. */ | ||||||
3569 | |||||||
3570 | if (m_split_insn == 0 && ! reg_overlap_mentioned_p (i2dest, newpat)) | ||||||
3571 | { | ||||||
3572 | machine_mode new_mode = GET_MODE (SET_DEST (newpat))((machine_mode) ((((newpat)->u.fld[0]).rt_rtx))->mode); | ||||||
3573 | |||||||
3574 | /* ??? Reusing i2dest without resetting the reg_stat entry for it | ||||||
3575 | (temporarily, until we are committed to this instruction | ||||||
3576 | combination) does not work: for example, any call to nonzero_bits | ||||||
3577 | on the register (from a splitter in the MD file, for example) | ||||||
3578 | will get the old information, which is invalid. | ||||||
3579 | |||||||
3580 | Since nowadays we can create registers during combine just fine, | ||||||
3581 | we should just create a new one here, not reuse i2dest. */ | ||||||
3582 | |||||||
3583 | /* First try to split using the original register as a | ||||||
3584 | scratch register. */ | ||||||
3585 | parallel = gen_rtx_PARALLEL (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((i2dest)) )))) ) | ||||||
3586 | gen_rtvec (2, newpat,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((i2dest)) )))) ) | ||||||
3587 | gen_rtx_CLOBBER (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((i2dest)) )))) ) | ||||||
3588 | i2dest)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((i2dest)) )))) ); | ||||||
3589 | m_split_insn = combine_split_insns (parallel, i3); | ||||||
3590 | |||||||
3591 | /* If that didn't work, try changing the mode of I2DEST if | ||||||
3592 | we can. */ | ||||||
3593 | if (m_split_insn == 0 | ||||||
3594 | && new_mode != GET_MODE (i2dest)((machine_mode) (i2dest)->mode) | ||||||
3595 | && new_mode != VOIDmode((void) 0, E_VOIDmode) | ||||||
3596 | && can_change_dest_mode (i2dest, added_sets_2, new_mode)) | ||||||
3597 | { | ||||||
3598 | machine_mode old_mode = GET_MODE (i2dest)((machine_mode) (i2dest)->mode); | ||||||
3599 | rtx ni2dest; | ||||||
3600 | |||||||
3601 | if (REGNO (i2dest)(rhs_regno(i2dest)) < FIRST_PSEUDO_REGISTER76) | ||||||
3602 | ni2dest = gen_rtx_REG (new_mode, REGNO (i2dest)(rhs_regno(i2dest))); | ||||||
3603 | else | ||||||
3604 | { | ||||||
3605 | subst_mode (REGNO (i2dest)(rhs_regno(i2dest)), new_mode); | ||||||
3606 | ni2dest = regno_reg_rtx[REGNO (i2dest)(rhs_regno(i2dest))]; | ||||||
3607 | } | ||||||
3608 | |||||||
3609 | parallel = (gen_rtx_PARALLELgen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((ni2dest)) )))) ) | ||||||
3610 | (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((ni2dest)) )))) ) | ||||||
3611 | gen_rtvec (2, newpat,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((ni2dest)) )))) ) | ||||||
3612 | gen_rtx_CLOBBER (VOIDmode,gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((ni2dest)) )))) ) | ||||||
3613 | ni2dest)))gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (gen_rtvec (2, newpat, gen_rtx_fmt_e_stat ((CLOBBER), ((((void ) 0, E_VOIDmode))), ((ni2dest)) )))) )); | ||||||
3614 | m_split_insn = combine_split_insns (parallel, i3); | ||||||
3615 | |||||||
3616 | if (m_split_insn == 0 | ||||||
3617 | && REGNO (i2dest)(rhs_regno(i2dest)) >= FIRST_PSEUDO_REGISTER76) | ||||||
3618 | { | ||||||
3619 | struct undo *buf; | ||||||
3620 | |||||||
3621 | adjust_reg_mode (regno_reg_rtx[REGNO (i2dest)(rhs_regno(i2dest))], old_mode); | ||||||
3622 | buf = undobuf.undos; | ||||||
3623 | undobuf.undos = buf->next; | ||||||
3624 | buf->next = undobuf.frees; | ||||||
3625 | undobuf.frees = buf; | ||||||
3626 | } | ||||||
3627 | } | ||||||
3628 | |||||||
3629 | i2scratch = m_split_insn != 0; | ||||||
3630 | } | ||||||
3631 | |||||||
3632 | /* If recog_for_combine has discarded clobbers, try to use them | ||||||
3633 | again for the split. */ | ||||||
3634 | if (m_split_insn == 0 && newpat_vec_with_clobbers) | ||||||
3635 | { | ||||||
3636 | parallel = gen_rtx_PARALLEL (VOIDmode, newpat_vec_with_clobbers)gen_rtx_fmt_E_stat ((PARALLEL), ((((void) 0, E_VOIDmode))), ( (newpat_vec_with_clobbers)) ); | ||||||
3637 | m_split_insn = combine_split_insns (parallel, i3); | ||||||
3638 | } | ||||||
3639 | |||||||
3640 | if (m_split_insn && NEXT_INSN (m_split_insn) == NULL_RTX(rtx) 0) | ||||||
3641 | { | ||||||
3642 | rtx m_split_pat = PATTERN (m_split_insn); | ||||||
3643 | insn_code_number = recog_for_combine (&m_split_pat, i3, &new_i3_notes); | ||||||
3644 | if (insn_code_number >= 0) | ||||||
3645 | newpat = m_split_pat; | ||||||
3646 | } | ||||||
3647 | else if (m_split_insn && NEXT_INSN (NEXT_INSN (m_split_insn)) == NULL_RTX(rtx) 0 | ||||||
3648 | && (next_nonnote_nondebug_insn (i2) == i3 | ||||||
3649 | || !modified_between_p (PATTERN (m_split_insn), i2, i3))) | ||||||
3650 | { | ||||||
3651 | rtx i2set, i3set; | ||||||
3652 | rtx newi3pat = PATTERN (NEXT_INSN (m_split_insn)); | ||||||
3653 | newi2pat = PATTERN (m_split_insn); | ||||||
3654 | |||||||
3655 | i3set = single_set (NEXT_INSN (m_split_insn)); | ||||||
3656 | i2set = single_set (m_split_insn); | ||||||
3657 | |||||||
3658 | i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); | ||||||
3659 | |||||||
3660 | /* If I2 or I3 has multiple SETs, we won't know how to track | ||||||
3661 | register status, so don't use these insns. If I2's destination | ||||||
3662 | is used between I2 and I3, we also can't use these insns. */ | ||||||
3663 | |||||||
3664 | if (i2_code_number >= 0 && i2set && i3set | ||||||
3665 | && (next_nonnote_nondebug_insn (i2) == i3 | ||||||
3666 | || ! reg_used_between_p (SET_DEST (i2set)(((i2set)->u.fld[0]).rt_rtx), i2, i3))) | ||||||
3667 | insn_code_number = recog_for_combine (&newi3pat, i3, | ||||||
3668 | &new_i3_notes); | ||||||
3669 | if (insn_code_number >= 0) | ||||||
3670 | newpat = newi3pat; | ||||||
3671 | |||||||
3672 | /* It is possible that both insns now set the destination of I3. | ||||||
3673 | If so, we must show an extra use of it. */ | ||||||
3674 | |||||||
3675 | if (insn_code_number >= 0) | ||||||
3676 | { | ||||||
3677 | rtx new_i3_dest = SET_DEST (i3set)(((i3set)->u.fld[0]).rt_rtx); | ||||||
3678 | rtx new_i2_dest = SET_DEST (i2set)(((i2set)->u.fld[0]).rt_rtx); | ||||||
3679 | |||||||
3680 | while (GET_CODE (new_i3_dest)((enum rtx_code) (new_i3_dest)->code) == ZERO_EXTRACT | ||||||
3681 | || GET_CODE (new_i3_dest)((enum rtx_code) (new_i3_dest)->code) == STRICT_LOW_PART | ||||||
3682 | || GET_CODE (new_i3_dest)((enum rtx_code) (new_i3_dest)->code) == SUBREG) | ||||||
3683 | new_i3_dest = XEXP (new_i3_dest, 0)(((new_i3_dest)->u.fld[0]).rt_rtx); | ||||||
3684 | |||||||
3685 | while (GET_CODE (new_i2_dest)((enum rtx_code) (new_i2_dest)->code) == ZERO_EXTRACT | ||||||
3686 | || GET_CODE (new_i2_dest)((enum rtx_code) (new_i2_dest)->code) == STRICT_LOW_PART | ||||||
3687 | || GET_CODE (new_i2_dest)((enum rtx_code) (new_i2_dest)->code) == SUBREG) | ||||||
3688 | new_i2_dest = XEXP (new_i2_dest, 0)(((new_i2_dest)->u.fld[0]).rt_rtx); | ||||||
3689 | |||||||
3690 | if (REG_P (new_i3_dest)(((enum rtx_code) (new_i3_dest)->code) == REG) | ||||||
3691 | && REG_P (new_i2_dest)(((enum rtx_code) (new_i2_dest)->code) == REG) | ||||||
3692 | && REGNO (new_i3_dest)(rhs_regno(new_i3_dest)) == REGNO (new_i2_dest)(rhs_regno(new_i2_dest)) | ||||||
3693 | && REGNO (new_i2_dest)(rhs_regno(new_i2_dest)) < reg_n_sets_max) | ||||||
3694 | INC_REG_N_SETS (REGNO (new_i2_dest), 1)(regstat_n_sets_and_refs[(rhs_regno(new_i2_dest))].sets += 1); | ||||||
3695 | } | ||||||
3696 | } | ||||||
3697 | |||||||
3698 | /* If we can split it and use I2DEST, go ahead and see if that | ||||||
3699 | helps things be recognized. Verify that none of the registers | ||||||
3700 | are set between I2 and I3. */ | ||||||
3701 | if (insn_code_number < 0 | ||||||
3702 | && (split = find_split_point (&newpat, i3, false)) != 0 | ||||||
3703 | /* We need I2DEST in the proper mode. If it is a hard register | ||||||
3704 | or the only use of a pseudo, we can change its mode. | ||||||
3705 | Make sure we don't change a hard register to have a mode that | ||||||
3706 | isn't valid for it, or change the number of registers. */ | ||||||
3707 | && (GET_MODE (*split)((machine_mode) (*split)->mode) == GET_MODE (i2dest)((machine_mode) (i2dest)->mode) | ||||||
3708 | || GET_MODE (*split)((machine_mode) (*split)->mode) == VOIDmode((void) 0, E_VOIDmode) | ||||||
3709 | || can_change_dest_mode (i2dest, added_sets_2, | ||||||
3710 | GET_MODE (*split)((machine_mode) (*split)->mode))) | ||||||
3711 | && (next_nonnote_nondebug_insn (i2) == i3 | ||||||
3712 | || !modified_between_p (*split, i2, i3)) | ||||||
3713 | /* We can't overwrite I2DEST if its value is still used by | ||||||
3714 | NEWPAT. */ | ||||||
3715 | && ! reg_referenced_p (i2dest, newpat) | ||||||
3716 | /* We should not split a possibly trapping part when we | ||||||
3717 | care about non-call EH and have REG_EH_REGION notes | ||||||
3718 | to distribute. */ | ||||||
3719 | && ! (cfun(cfun + 0)->can_throw_non_call_exceptions | ||||||
3720 | && has_non_call_exception | ||||||
3721 | && may_trap_p (*split))) | ||||||
3722 | { | ||||||
3723 | rtx newdest = i2dest; | ||||||
3724 | enum rtx_code split_code = GET_CODE (*split)((enum rtx_code) (*split)->code); | ||||||
3725 | machine_mode split_mode = GET_MODE (*split)((machine_mode) (*split)->mode); | ||||||
3726 | bool subst_done = false; | ||||||
3727 | newi2pat = NULL_RTX(rtx) 0; | ||||||
3728 | |||||||
3729 | i2scratch = true; | ||||||
3730 | |||||||
3731 | /* *SPLIT may be part of I2SRC, so make sure we have the | ||||||
3732 | original expression around for later debug processing. | ||||||
3733 | We should not need I2SRC any more in other cases. */ | ||||||
3734 | if (MAY_HAVE_DEBUG_BIND_INSNSglobal_options.x_flag_var_tracking_assignments) | ||||||
3735 | i2src = copy_rtx (i2src); | ||||||
3736 | else | ||||||
3737 | i2src = NULLnullptr; | ||||||
3738 | |||||||
3739 | /* Get NEWDEST as a register in the proper mode. We have already | ||||||
3740 | validated that we can do this. */ | ||||||
3741 | if (GET_MODE (i2dest)((machine_mode) (i2dest)->mode) != split_mode && split_mode != VOIDmode((void) 0, E_VOIDmode)) | ||||||
3742 | { | ||||||
3743 | if (REGNO (i2dest)(rhs_regno(i2dest)) < FIRST_PSEUDO_REGISTER76) | ||||||
3744 | newdest = gen_rtx_REG (split_mode, REGNO (i2dest)(rhs_regno(i2dest))); | ||||||
3745 | else | ||||||
3746 | { | ||||||
3747 | subst_mode (REGNO (i2dest)(rhs_regno(i2dest)), split_mode); | ||||||
3748 | newdest = regno_reg_rtx[REGNO (i2dest)(rhs_regno(i2dest))]; | ||||||
3749 | } | ||||||
3750 | } | ||||||
3751 | |||||||
3752 | /* If *SPLIT is a (mult FOO (const_int pow2)), convert it to | ||||||
3753 | an ASHIFT. This can occur if it was inside a PLUS and hence | ||||||
3754 | appeared to be a memory address. This is a kludge. */ | ||||||
3755 | if (split_code == MULT | ||||||
3756 | && CONST_INT_P (XEXP (*split, 1))(((enum rtx_code) ((((*split)->u.fld[1]).rt_rtx))->code ) == CONST_INT) | ||||||
3757 | && INTVAL (XEXP (*split, 1))(((((*split)->u.fld[1]).rt_rtx))->u.hwint[0]) > 0 | ||||||
3758 | && (i = exact_log2 (UINTVAL (XEXP (*split, 1))((unsigned long) (((((*split)->u.fld[1]).rt_rtx))->u.hwint [0])))) >= 0) | ||||||
3759 | { | ||||||
3760 | rtx i_rtx = gen_int_shift_amount (split_mode, i); | ||||||
3761 | SUBST (*split, gen_rtx_ASHIFT (split_mode,do_SUBST (&(*split), (gen_rtx_fmt_ee_stat ((ASHIFT), ((split_mode )), (((((*split)->u.fld[0]).rt_rtx))), ((i_rtx)) ))) | ||||||
3762 | XEXP (*split, 0), i_rtx))do_SUBST (&(*split), (gen_rtx_fmt_ee_stat ((ASHIFT), ((split_mode )), (((((*split)->u.fld[0]).rt_rtx))), ((i_rtx)) ))); | ||||||
3763 | /* Update split_code because we may not have a multiply | ||||||
3764 | anymore. */ | ||||||
3765 | split_code = GET_CODE (*split)((enum rtx_code) (*split)->code); | ||||||
3766 | } | ||||||
3767 | |||||||
3768 | /* Similarly for (plus (mult FOO (const_int pow2))). */ | ||||||
3769 | if (split_code == PLUS | ||||||
3770 | && GET_CODE (XEXP (*split, 0))((enum rtx_code) ((((*split)->u.fld[0]).rt_rtx))->code) == MULT | ||||||
3771 | && CONST_INT_P (XEXP (XEXP (*split, 0), 1))(((enum rtx_code) (((((((*split)->u.fld[0]).rt_rtx))->u .fld[1]).rt_rtx))->code) == CONST_INT) | ||||||
3772 | && INTVAL (XEXP (XEXP (*split, 0), 1))((((((((*split)->u.fld[0]).rt_rtx))->u.fld[1]).rt_rtx)) ->u.hwint[0]) > 0 | ||||||
3773 | && (i = exact_log2 (UINTVAL (XEXP (XEXP (*split, 0), 1))((unsigned long) ((((((((*split)->u.fld[0]).rt_rtx))->u .fld[1]).rt_rtx))->u.hwint[0])))) >= 0) | ||||||
3774 | { | ||||||
3775 | rtx nsplit = XEXP (*split, 0)(((*split)->u.fld[0]).rt_rtx); | ||||||
3776 | rtx i_rtx = gen_int_shift_amount (GET_MODE (nsplit)((machine_mode) (nsplit)->mode), i); | ||||||
3777 | SUBST (XEXP (*split, 0), gen_rtx_ASHIFT (GET_MODE (nsplit),do_SUBST (&((((*split)->u.fld[0]).rt_rtx)), (gen_rtx_fmt_ee_stat ((ASHIFT), ((((machine_mode) (nsplit)->mode))), (((((nsplit )->u.fld[0]).rt_rtx))), ((i_rtx)) ))) | ||||||
3778 | XEXP (nsplit, 0),do_SUBST (&((((*split)->u.fld[0]).rt_rtx)), (gen_rtx_fmt_ee_stat ((ASHIFT), ((((machine_mode) (nsplit)->mode))), (((((nsplit )->u.fld[0]).rt_rtx))), ((i_rtx)) ))) | ||||||
3779 | i_rtx))do_SUBST (&((((*split)->u.fld[0]).rt_rtx)), (gen_rtx_fmt_ee_stat ((ASHIFT), ((((machine_mode) (nsplit)->mode))), (((((nsplit )->u.fld[0]).rt_rtx))), ((i_rtx)) ))); | ||||||
3780 | /* Update split_code because we may not have a multiply | ||||||
3781 | anymore. */ | ||||||
3782 | split_code = GET_CODE (*split)((enum rtx_code) (*split)->code); | ||||||
3783 | } | ||||||
3784 | |||||||
3785 | #ifdef INSN_SCHEDULING | ||||||
3786 | /* If *SPLIT is a paradoxical SUBREG, when we split it, it should | ||||||
3787 | be written as a ZERO_EXTEND. */ | ||||||
3788 | if (split_code == SUBREG && MEM_P (SUBREG_REG (*split))(((enum rtx_code) ((((*split)->u.fld[0]).rt_rtx))->code ) == MEM)) | ||||||
3789 | { | ||||||
3790 | /* Or as a SIGN_EXTEND if LOAD_EXTEND_OP says that that's | ||||||
3791 | what it really is. */ | ||||||
3792 | if (load_extend_op (GET_MODE (SUBREG_REG (*split))((machine_mode) ((((*split)->u.fld[0]).rt_rtx))->mode)) | ||||||
3793 | == SIGN_EXTEND) | ||||||
3794 | SUBST (*split, gen_rtx_SIGN_EXTEND (split_mode,do_SUBST (&(*split), (gen_rtx_fmt_e_stat ((SIGN_EXTEND), ( (split_mode)), (((((*split)->u.fld[0]).rt_rtx))) ))) | ||||||
3795 | SUBREG_REG (*split)))do_SUBST (&(*split), (gen_rtx_fmt_e_stat ((SIGN_EXTEND), ( (split_mode)), (((((*split)->u.fld[0]).rt_rtx))) ))); | ||||||
3796 | else | ||||||
3797 | SUBST (*split, gen_rtx_ZERO_EXTEND (split_mode,do_SUBST (&(*split), (gen_rtx_fmt_e_stat ((ZERO_EXTEND), ( (split_mode)), (((((*split)->u.fld[0]).rt_rtx))) ))) | ||||||
3798 | SUBREG_REG (*split)))do_SUBST (&(*split), (gen_rtx_fmt_e_stat ((ZERO_EXTEND), ( (split_mode)), (((((*split)->u.fld[0]).rt_rtx))) ))); | ||||||
3799 | } | ||||||
3800 | #endif | ||||||
3801 | |||||||
3802 | /* Attempt to split binary operators using arithmetic identities. */ | ||||||
3803 | if (BINARY_P (SET_SRC (newpat))(((rtx_class[(int) (((enum rtx_code) ((((newpat)->u.fld[1] ).rt_rtx))->code))]) & (~3)) == (RTX_COMPARE & (~3 ))) | ||||||
3804 | && split_mode == GET_MODE (SET_SRC (newpat))((machine_mode) ((((newpat)->u.fld[1]).rt_rtx))->mode) | ||||||
3805 | && ! side_effects_p (SET_SRC (newpat)(((newpat)->u.fld[1]).rt_rtx))) | ||||||
3806 | { | ||||||
3807 | rtx setsrc = SET_SRC (newpat)(((newpat)->u.fld[1]).rt_rtx); | ||||||
3808 | machine_mode mode = GET_MODE (setsrc)((machine_mode) (setsrc)->mode); | ||||||
3809 | enum rtx_code code = GET_CODE (setsrc)((enum rtx_code) (setsrc)->code); | ||||||
3810 | rtx src_op0 = XEXP (setsrc, 0)(((setsrc)->u.fld[0]).rt_rtx); | ||||||
3811 | rtx src_op1 = XEXP (setsrc, 1)(((setsrc)->u.fld[1]).rt_rtx); | ||||||
3812 | |||||||
3813 | /* Split "X = Y op Y" as "Z = Y; X = Z op Z". */ | ||||||
3814 | if (rtx_equal_p (src_op0, src_op1)) | ||||||
3815 | { | ||||||
3816 | newi2pat = gen_rtx_SET (newdest, src_op0)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((newdest )), ((src_op0)) ); | ||||||
3817 | SUBST (XEXP (setsrc, 0), newdest)do_SUBST (&((((setsrc)->u.fld[0]).rt_rtx)), (newdest)); | ||||||
3818 | SUBST (XEXP (setsrc, 1), newdest)do_SUBST (&((((setsrc)->u.fld[1]).rt_rtx)), (newdest)); | ||||||
3819 | subst_done = true; | ||||||
3820 | } | ||||||
3821 | /* Split "((P op Q) op R) op S" where op is PLUS or MULT. */ | ||||||
3822 | else if ((code == PLUS || code == MULT) | ||||||
3823 | && GET_CODE (src_op0)((enum rtx_code) (src_op0)->code) == code | ||||||
3824 | && GET_CODE (XEXP (src_op0, 0))((enum rtx_code) ((((src_op0)->u.fld[0]).rt_rtx))->code ) == code | ||||||
3825 | && (INTEGRAL_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_INT || ((enum mode_class ) mode_class[mode]) == MODE_PARTIAL_INT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_INT || ((enum mode_class) mode_class [mode]) == MODE_VECTOR_BOOL || ((enum mode_class) mode_class[ mode]) == MODE_VECTOR_INT) | ||||||
3826 | || (FLOAT_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_DECIMAL_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_COMPLEX_FLOAT || ((enum mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT) | ||||||
3827 | && flag_unsafe_math_optimizationsglobal_options.x_flag_unsafe_math_optimizations))) | ||||||
3828 | { | ||||||
3829 | rtx p = XEXP (XEXP (src_op0, 0), 0)((((((src_op0)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx); | ||||||
3830 | rtx q = XEXP (XEXP (src_op0, 0), 1)((((((src_op0)->u.fld[0]).rt_rtx))->u.fld[1]).rt_rtx); | ||||||
3831 | rtx r = XEXP (src_op0, 1)(((src_op0)->u.fld[1]).rt_rtx); | ||||||
3832 | rtx s = src_op1; | ||||||
3833 | |||||||
3834 | /* Split both "((X op Y) op X) op Y" and | ||||||
3835 | "((X op Y) op Y) op X" as "T op T" where T is | ||||||
3836 | "X op Y". */ | ||||||
3837 | if ((rtx_equal_p (p,r) && rtx_equal_p (q,s)) | ||||||
3838 | || (rtx_equal_p (p,s) && rtx_equal_p (q,r))) | ||||||
3839 | { | ||||||
3840 | newi2pat = gen_rtx_SET (newdest, XEXP (src_op0, 0))gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((newdest )), (((((src_op0)->u.fld[0]).rt_rtx))) ); | ||||||
3841 | SUBST (XEXP (setsrc, 0), newdest)do_SUBST (&((((setsrc)->u.fld[0]).rt_rtx)), (newdest)); | ||||||
3842 | SUBST (XEXP (setsrc, 1), newdest)do_SUBST (&((((setsrc)->u.fld[1]).rt_rtx)), (newdest)); | ||||||
3843 | subst_done = true; | ||||||
3844 | } | ||||||
3845 | /* Split "((X op X) op Y) op Y)" as "T op T" where | ||||||
3846 | T is "X op Y". */ | ||||||
3847 | else if (rtx_equal_p (p,q) && rtx_equal_p (r,s)) | ||||||
3848 | { | ||||||
3849 | rtx tmp = simplify_gen_binary (code, mode, p, r); | ||||||
3850 | newi2pat = gen_rtx_SET (newdest, tmp)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((newdest )), ((tmp)) ); | ||||||
3851 | SUBST (XEXP (setsrc, 0), newdest)do_SUBST (&((((setsrc)->u.fld[0]).rt_rtx)), (newdest)); | ||||||
3852 | SUBST (XEXP (setsrc, 1), newdest)do_SUBST (&((((setsrc)->u.fld[1]).rt_rtx)), (newdest)); | ||||||
3853 | subst_done = true; | ||||||
3854 | } | ||||||
3855 | } | ||||||
3856 | } | ||||||
3857 | |||||||
3858 | if (!subst_done) | ||||||
3859 | { | ||||||
3860 | newi2pat = gen_rtx_SET (newdest, *split)gen_rtx_fmt_ee_stat ((SET), (((void) 0, E_VOIDmode)), ((newdest )), ((*split)) ); | ||||||
3861 | SUBST (*split, newdest)do_SUBST (&(*split), (newdest)); | ||||||
3862 | } | ||||||
3863 | |||||||
3864 | i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); | ||||||
3865 | |||||||
3866 | /* recog_for_combine might have added CLOBBERs to newi2pat. | ||||||
3867 | Make sure NEWPAT does not depend on the clobbered regs. */ | ||||||
3868 | if (GET_CODE (newi2pat)((enum rtx_code) (newi2pat)->code) == PARALLEL) | ||||||
3869 | for (i = XVECLEN (newi2pat, 0)(((((newi2pat)->u.fld[0]).rt_rtvec))->num_elem) - 1; i >= 0; i--) | ||||||
3870 | if (GET_CODE (XVECEXP (newi2pat, 0, i))((enum rtx_code) ((((((newi2pat)->u.fld[0]).rt_rtvec))-> elem[i]))->code) == CLOBBER) | ||||||
3871 | { | ||||||
3872 | rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0)((((((((newi2pat)->u.fld[0]).rt_rtvec))->elem[i]))-> u.fld[0]).rt_rtx); | ||||||
3873 | if (reg_overlap_mentioned_p (reg, newpat)) | ||||||
3874 | { | ||||||
3875 | undo_all (); | ||||||
3876 | return 0; | ||||||
3877 | } | ||||||
3878 | } | ||||||
3879 | |||||||
3880 | /* If the split point was a MULT and we didn't have one before, | ||||||
3881 | don't use one now. */ | ||||||
3882 | if (i2_code_number >= 0 && ! (split_code == MULT && ! have_mult)) | ||||||
3883 | insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); | ||||||
3884 | } | ||||||
3885 | } | ||||||
3886 | |||||||
3887 | /* Check for a case where we loaded from memory in a narrow mode and | ||||||
3888 | then sign extended it, but we need both registers. In that case, | ||||||
3889 | we have a PARALLEL with both loads from the same memory location. | ||||||
3890 | We can split this into a load from memory followed by a register-register | ||||||
3891 | copy. This saves at least one insn, more if register allocation can | ||||||
3892 | eliminate the copy. | ||||||
3893 | |||||||
3894 | We cannot do this if the destination of the first assignment is a | ||||||
3895 | condition code register. We eliminate this case by making sure | ||||||
3896 | the SET_DEST and SET_SRC have the same mode. | ||||||
3897 | |||||||
3898 | We cannot do this if the destination of the second assignment is | ||||||
3899 | a register that we have already assumed is zero-extended. Similarly | ||||||
3900 | for a SUBREG of such a register. */ | ||||||
3901 | |||||||
3902 | else if (i1
| ||||||
3903 | && GET_CODE (newpat)((enum rtx_code) (newpat)->code) == PARALLEL | ||||||
3904 | && XVECLEN (newpat, 0)(((((newpat)->u.fld[0]).rt_rtvec))->num_elem) == 2 | ||||||
3905 | && GET_CODE (XVECEXP (newpat, 0, 0))((enum rtx_code) ((((((newpat)->u.fld[0]).rt_rtvec))->elem [0]))->code) == SET | ||||||
3906 | && GET_CODE (SET_SRC (XVECEXP (newpat, 0, 0)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[0]))->u.fld[1]).rt_rtx))->code) == SIGN_EXTEND | ||||||
3907 | && (GET_MODE (SET_DEST (XVECEXP (newpat, 0, 0)))((machine_mode) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[0]))->u.fld[0]).rt_rtx))->mode) | ||||||
3908 | == GET_MODE (SET_SRC (XVECEXP (newpat, 0, 0)))((machine_mode) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[0]))->u.fld[1]).rt_rtx))->mode)) | ||||||
3909 | && GET_CODE (XVECEXP (newpat, 0, 1))((enum rtx_code) ((((((newpat)->u.fld[0]).rt_rtvec))->elem [1]))->code) == SET | ||||||
3910 | && rtx_equal_p (SET_SRC (XVECEXP (newpat, 0, 1))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))->u. fld[1]).rt_rtx), | ||||||
3911 | XEXP (SET_SRC (XVECEXP (newpat, 0, 0)), 0)(((((((((((newpat)->u.fld[0]).rt_rtvec))->elem[0]))-> u.fld[1]).rt_rtx))->u.fld[0]).rt_rtx)) | ||||||
3912 | && !modified_between_p (SET_SRC (XVECEXP (newpat, 0, 1))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))->u. fld[1]).rt_rtx), i2, i3) | ||||||
3913 | && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[1]))->u.fld[0]).rt_rtx))->code) != ZERO_EXTRACT | ||||||
3914 | && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[1]))->u.fld[0]).rt_rtx))->code) != STRICT_LOW_PART | ||||||
3915 | && ! (temp_expr = SET_DEST (XVECEXP (newpat, 0, 1))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))->u. fld[0]).rt_rtx), | ||||||
3916 | (REG_P (temp_expr)(((enum rtx_code) (temp_expr)->code) == REG) | ||||||
3917 | && reg_stat[REGNO (temp_expr)(rhs_regno(temp_expr))].nonzero_bits != 0 | ||||||
3918 | && known_lt (GET_MODE_PRECISION (GET_MODE (temp_expr)),(!maybe_le (((8) * (((global_options.x_ix86_isa_flags & ( 1UL << 1)) != 0) ? 8 : 4)), GET_MODE_PRECISION (((machine_mode ) (temp_expr)->mode)))) | ||||||
3919 | BITS_PER_WORD)(!maybe_le (((8) * (((global_options.x_ix86_isa_flags & ( 1UL << 1)) != 0) ? 8 : 4)), GET_MODE_PRECISION (((machine_mode ) (temp_expr)->mode)))) | ||||||
3920 | && known_lt (GET_MODE_PRECISION (GET_MODE (temp_expr)),(!maybe_le ((8 * 4), GET_MODE_PRECISION (((machine_mode) (temp_expr )->mode)))) | ||||||
3921 | HOST_BITS_PER_INT)(!maybe_le ((8 * 4), GET_MODE_PRECISION (((machine_mode) (temp_expr )->mode)))) | ||||||
3922 | && (reg_stat[REGNO (temp_expr)(rhs_regno(temp_expr))].nonzero_bits | ||||||
3923 | != GET_MODE_MASK (word_mode)mode_mask_array[word_mode]))) | ||||||
3924 | && ! (GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[1]))->u.fld[0]).rt_rtx))->code) == SUBREG | ||||||
3925 | && (temp_expr = SUBREG_REG (SET_DEST (XVECEXP (newpat, 0, 1)))(((((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))-> u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx), | ||||||
3926 | (REG_P (temp_expr)(((enum rtx_code) (temp_expr)->code) == REG) | ||||||
3927 | && reg_stat[REGNO (temp_expr)(rhs_regno(temp_expr))].nonzero_bits != 0 | ||||||
3928 | && known_lt (GET_MODE_PRECISION (GET_MODE (temp_expr)),(!maybe_le (((8) * (((global_options.x_ix86_isa_flags & ( 1UL << 1)) != 0) ? 8 : 4)), GET_MODE_PRECISION (((machine_mode ) (temp_expr)->mode)))) | ||||||
3929 | BITS_PER_WORD)(!maybe_le (((8) * (((global_options.x_ix86_isa_flags & ( 1UL << 1)) != 0) ? 8 : 4)), GET_MODE_PRECISION (((machine_mode ) (temp_expr)->mode)))) | ||||||
3930 | && known_lt (GET_MODE_PRECISION (GET_MODE (temp_expr)),(!maybe_le ((8 * 4), GET_MODE_PRECISION (((machine_mode) (temp_expr )->mode)))) | ||||||
3931 | HOST_BITS_PER_INT)(!maybe_le ((8 * 4), GET_MODE_PRECISION (((machine_mode) (temp_expr )->mode)))) | ||||||
3932 | && (reg_stat[REGNO (temp_expr)(rhs_regno(temp_expr))].nonzero_bits | ||||||
3933 | != GET_MODE_MASK (word_mode)mode_mask_array[word_mode])))) | ||||||
3934 | && ! reg_overlap_mentioned_p (SET_DEST (XVECEXP (newpat, 0, 1))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))->u. fld[0]).rt_rtx), | ||||||
3935 | SET_SRC (XVECEXP (newpat, 0, 1))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))->u. fld[1]).rt_rtx)) | ||||||
3936 | && ! find_reg_note (i3, REG_UNUSED, | ||||||
3937 | SET_DEST (XVECEXP (newpat, 0, 0))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[0]))->u. fld[0]).rt_rtx))) | ||||||
3938 | { | ||||||
3939 | rtx ni2dest; | ||||||
3940 | |||||||
3941 | newi2pat = XVECEXP (newpat, 0, 0)(((((newpat)->u.fld[0]).rt_rtvec))->elem[0]); | ||||||
3942 | ni2dest = SET_DEST (XVECEXP (newpat, 0, 0))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[0]))->u. fld[0]).rt_rtx); | ||||||
3943 | newpat = XVECEXP (newpat, 0, 1)(((((newpat)->u.fld[0]).rt_rtvec))->elem[1]); | ||||||
3944 | SUBST (SET_SRC (newpat),do_SUBST (&((((newpat)->u.fld[1]).rt_rtx)), (rtl_hooks .gen_lowpart (((machine_mode) ((((newpat)->u.fld[1]).rt_rtx ))->mode), ni2dest))) | ||||||
3945 | gen_lowpart (GET_MODE (SET_SRC (newpat)), ni2dest))do_SUBST (&((((newpat)->u.fld[1]).rt_rtx)), (rtl_hooks .gen_lowpart (((machine_mode) ((((newpat)->u.fld[1]).rt_rtx ))->mode), ni2dest))); | ||||||
3946 | i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); | ||||||
3947 | |||||||
3948 | if (i2_code_number >= 0) | ||||||
3949 | insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); | ||||||
3950 | |||||||
3951 | if (insn_code_number >= 0) | ||||||
3952 | swap_i2i3 = 1; | ||||||
3953 | } | ||||||
3954 | |||||||
3955 | /* Similarly, check for a case where we have a PARALLEL of two independent | ||||||
3956 | SETs but we started with three insns. In this case, we can do the sets | ||||||
3957 | as two separate insns. This case occurs when some SET allows two | ||||||
3958 | other insns to combine, but the destination of that SET is still live. | ||||||
3959 | |||||||
3960 | Also do this if we started with two insns and (at least) one of the | ||||||
3961 | resulting sets is a noop; this noop will be deleted later. | ||||||
3962 | |||||||
3963 | Also do this if we started with two insns neither of which was a simple | ||||||
3964 | move. */ | ||||||
3965 | |||||||
3966 | else if (insn_code_number
| ||||||
3967 | && GET_CODE (newpat)((enum rtx_code) (newpat)->code) == PARALLEL | ||||||
3968 | && XVECLEN (newpat, 0)(((((newpat)->u.fld[0]).rt_rtvec))->num_elem) == 2 | ||||||
3969 | && GET_CODE (XVECEXP (newpat, 0, 0))((enum rtx_code) ((((((newpat)->u.fld[0]).rt_rtvec))->elem [0]))->code) == SET | ||||||
3970 | && GET_CODE (XVECEXP (newpat, 0, 1))((enum rtx_code) ((((((newpat)->u.fld[0]).rt_rtvec))->elem [1]))->code) == SET | ||||||
3971 | && (i1 | ||||||
3972 | || set_noop_p (XVECEXP (newpat, 0, 0)(((((newpat)->u.fld[0]).rt_rtvec))->elem[0])) | ||||||
3973 | || set_noop_p (XVECEXP (newpat, 0, 1)(((((newpat)->u.fld[0]).rt_rtvec))->elem[1])) | ||||||
3974 | || (!i2_was_move && !i3_was_move)) | ||||||
3975 | && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[0]))->u.fld[0]).rt_rtx))->code) != ZERO_EXTRACT | ||||||
3976 | && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 0)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[0]))->u.fld[0]).rt_rtx))->code) != STRICT_LOW_PART | ||||||
3977 | && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[1]))->u.fld[0]).rt_rtx))->code) != ZERO_EXTRACT | ||||||
3978 | && GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1)))((enum rtx_code) (((((((((newpat)->u.fld[0]).rt_rtvec))-> elem[1]))->u.fld[0]).rt_rtx))->code) != STRICT_LOW_PART | ||||||
3979 | && ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 1))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))->u. fld[0]).rt_rtx), | ||||||
3980 | XVECEXP (newpat, 0, 0)(((((newpat)->u.fld[0]).rt_rtvec))->elem[0])) | ||||||
3981 | && ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 0))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[0]))->u. fld[0]).rt_rtx), | ||||||
3982 | XVECEXP (newpat, 0, 1)(((((newpat)->u.fld[0]).rt_rtvec))->elem[1])) | ||||||
3983 | && ! (contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 0))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[0]))->u. fld[1]).rt_rtx)) | ||||||
3984 | && contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1))((((((((newpat)->u.fld[0]).rt_rtvec))->elem[1]))->u. fld[1]).rt_rtx)))) | ||||||
3985 | { | ||||||
3986 | rtx set0 = XVECEXP (newpat, 0, 0)(((((newpat)->u.fld[0]).rt_rtvec))->elem[0]); | ||||||
3987 | rtx set1 = XVECEXP (newpat, 0, 1)(((((newpat)->u.fld[0]).rt_rtvec))->elem[1]); | ||||||
3988 | |||||||
3989 | /* Normally, it doesn't matter which of the two is done first, but | ||||||
3990 | one which uses any regs/memory set in between i2 and i3 can't | ||||||
3991 | be first. The PARALLEL might also have been pre-existing in i3, | ||||||
3992 | so we need to make sure that we won't wrongly hoist a SET to i2 | ||||||
3993 | that would conflict with a death note present in there, or would | ||||||
3994 | have its dest modified between i2 and i3. */ | ||||||
3995 | if (!modified_between_p (SET_SRC (set1)(((set1)->u.fld[1]).rt_rtx), i2, i3) | ||||||
3996 | && !(REG_P (SET_DEST (set1))(((enum rtx_code) ((((set1)->u.fld[0]).rt_rtx))->code) == REG) | ||||||
3997 | && find_reg_note (i2, REG_DEAD, SET_DEST (set1)(((set1)->u.fld[0]).rt_rtx))) | ||||||
3998 | && !(GET_CODE (SET_DEST (set1))((enum rtx_code) ((((set1)->u.fld[0]).rt_rtx))->code) == SUBREG | ||||||
3999 | && find_reg_note (i2, REG_DEAD, | ||||||
4000 | SUBREG_REG (SET_DEST (set1))((((((set1)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx))) | ||||||
4001 | && !modified_between_p (SET_DEST (set1)(((set1)->u.fld[0]).rt_rtx), i2, i3) | ||||||
4002 | /* If I3 is a jump, ensure that set0 is a jump so that | ||||||
4003 | we do not create invalid RTL. */ | ||||||
4004 | && (!JUMP_P (i3)(((enum rtx_code) (i3)->code) == JUMP_INSN) || SET_DEST (set0)(((set0)->u.fld[0]).rt_rtx) == pc_rtx) | ||||||
4005 | ) | ||||||
4006 | { | ||||||
4007 | newi2pat = set1; | ||||||
4008 | newpat = set0; | ||||||
4009 | } | ||||||
4010 | else if (!modified_between_p (SET_SRC (set0)(((set0)->u.fld[1]).rt_rtx), i2, i3) | ||||||
4011 | && !(REG_P (SET_DEST (set0))(((enum rtx_code) ((((set0)->u.fld[0]).rt_rtx))->code) == REG) | ||||||
4012 | && find_reg_note (i2, REG_DEAD, SET_DEST (set0)(((set0)->u.fld[0]).rt_rtx))) | ||||||
4013 | && !(GET_CODE (SET_DEST (set0))((enum rtx_code) ((((set0)->u.fld[0]).rt_rtx))->code) == SUBREG | ||||||
4014 | && find_reg_note (i2, REG_DEAD, | ||||||
4015 | SUBREG_REG (SET_DEST (set0))((((((set0)->u.fld[0]).rt_rtx))->u.fld[0]).rt_rtx))) | ||||||
4016 | && !modified_between_p (SET_DEST (set0)(((set0)->u.fld[0]).rt_rtx), i2, i3) | ||||||
4017 | /* If I3 is a jump, ensure that set1 is a jump so that | ||||||
4018 | we do not create invalid RTL. */ | ||||||
4019 | && (!JUMP_P (i3)(((enum rtx_code) (i3)->code) == JUMP_INSN) || SET_DEST (set1)(((set1)->u.fld[0]).rt_rtx) == pc_rtx) | ||||||
4020 | ) | ||||||
4021 | { | ||||||
4022 | newi2pat = set0; | ||||||
4023 | newpat = set1; | ||||||
4024 | } | ||||||
4025 | else | ||||||
4026 | { | ||||||
4027 | undo_all (); | ||||||
4028 | return 0; | ||||||
4029 | } | ||||||
4030 | |||||||
4031 | i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); | ||||||
4032 | |||||||
4033 | if (i2_code_number >= 0) | ||||||
4034 | { | ||||||
4035 | /* recog_for_combine might have added CLOBBERs to newi2pat. | ||||||
4036 | Make sure NEWPAT does not depend on the clobbered regs. */ | ||||||
4037 | if (GET_CODE (newi2pat)((enum rtx_code) (newi2pat)->code) == PARALLEL) | ||||||
4038 | { | ||||||
4039 | for (i = XVECLEN (newi2pat, 0)(((((newi2pat)->u.fld[0]).rt_rtvec))->num_elem) - 1; i >= 0; i--) | ||||||
4040 | if (GET_CODE (XVECEXP (newi2pat, 0, i))((enum rtx_code) ((((((newi2pat)->u.fld[0]).rt_rtvec))-> elem[i]))->code) == CLOBBER) | ||||||
4041 | { | ||||||
4042 | rtx reg = XEXP (XVECEXP (newi2pat, 0, i), 0)((((((((newi2pat)->u.fld[0]).rt_rtvec))->elem[i]))-> u.fld[0]).rt_rtx); | ||||||
4043 | if (reg_overlap_mentioned_p (reg, newpat)) | ||||||
4044 | { | ||||||
4045 | undo_all (); | ||||||
4046 | return 0; | ||||||
4047 | } | ||||||
4048 | } | ||||||
4049 | } | ||||||
4050 | |||||||
4051 | insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); | ||||||
4052 | |||||||
4053 | /* Likewise, recog_for_combine might have added clobbers to NEWPAT. | ||||||
4054 | Checking that the SET0's SET_DEST and SET1's SET_DEST aren't | ||||||
4055 | mentioned/clobbered, ensures NEWI2PAT's SET_DEST is live. */ | ||||||
4056 | if (insn_code_number >= 0 && GET_CODE (newpat)((enum rtx_code) (newpat)->code) == PARALLEL) | ||||||
4057 | { | ||||||
4058 | for (i = XVECLEN (newpat, 0)(((((newpat)->u.fld[0]).rt_rtvec))->num_elem) - 1; i >= 0; i--) | ||||||
4059 | if (GET_CODE (XVECEXP (newpat, 0, i))((enum rtx_code) ((((((newpat)->u.fld[0]).rt_rtvec))->elem [i]))->code) == CLOBBER) | ||||||
4060 | { | ||||||
4061 | rtx reg = XEXP (XVECEXP (newpat, 0, i), 0)((((((((newpat)->u.fld[0]).rt_rtvec))->elem[i]))->u. fld[0]).rt_rtx); | ||||||
4062 | if (reg_overlap_mentioned_p (reg, SET_DEST (set0)(((set0)->u.fld[0]).rt_rtx)) | ||||||
4063 | || reg_overlap_mentioned_p (reg, SET_DEST (set1)(((set1)->u.fld[0]).rt_rtx))) | ||||||
4064 | { | ||||||
4065 | undo_all (); | ||||||
4066 | return 0; | ||||||
4067 | } | ||||||
4068 | } | ||||||
4069 | } | ||||||
4070 | |||||||
4071 | if (insn_code_number >= 0) | ||||||
4072 | split_i2i3 = 1; | ||||||
4073 | } | ||||||
4074 | } | ||||||
4075 | |||||||
4076 | /* If it still isn't recognized, fail and change things back the way they | ||||||
4077 | were. */ | ||||||
4078 | if ((insn_code_number
| ||||||
4079 | /* Is the result a reasonable ASM_OPERANDS? */ | ||||||
4080 | && (! check_asm_operands (newpat) || added_sets_1
| ||||||
4081 | { | ||||||
4082 | undo_all (); | ||||||
4083 | return 0; | ||||||
4084 | } | ||||||
4085 | |||||||
4086 | /* If we had to change another insn, make sure it is valid also. */ | ||||||
4087 | if (undobuf.other_insn) | ||||||
4088 | { | ||||||
4089 | CLEAR_HARD_REG_SET (newpat_used_regs); | ||||||
4090 | |||||||
4091 | other_pat = PATTERN (undobuf.other_insn); | ||||||
4092 | other_code_number = recog_for_combine (&other_pat, undobuf.other_insn, | ||||||
4093 | &new_other_notes); | ||||||
4094 | |||||||
4095 | if (other_code_number < 0 && ! check_asm_operands (other_pat)) | ||||||
4096 | { | ||||||
4097 | undo_all (); | ||||||
4098 | return 0; | ||||||
4099 | } | ||||||
4100 | } | ||||||
4101 | |||||||
4102 | /* Only allow this combination if insn_cost reports that the | ||||||
4103 | replacement instructions are cheaper than the originals. */ | ||||||
4104 | if (!combine_validate_cost (i0, i1, i2, i3, newpat, newi2pat, other_pat)) | ||||||
4105 | { | ||||||
4106 | undo_all (); | ||||||
4107 | return 0; | ||||||
4108 | } | ||||||
4109 | |||||||
4110 | if (MAY_HAVE_DEBUG_BIND_INSNSglobal_options.x_flag_var_tracking_assignments) | ||||||
4111 | { | ||||||
4112 | struct undo *undo; | ||||||
4113 | |||||||
4114 | for (undo = undobuf.undos; undo; undo = undo->next) | ||||||
4115 | if (undo->kind == UNDO_MODE) | ||||||
4116 | { | ||||||
4117 | rtx reg = regno_reg_rtx[undo->where.regno]; | ||||||
4118 | machine_mode new_mode = GET_MODE (reg)((machine_mode) (reg)->mode); | ||||||
4119 | machine_mode old_mode = undo->old_contents.m; | ||||||
4120 | |||||||
4121 | /* Temporarily revert mode back. */ | ||||||
4122 | adjust_reg_mode (reg, old_mode); | ||||||
4123 | |||||||
4124 | if (reg == i2dest && i2scratch) | ||||||
4125 | { | ||||||
4126 | /* If we used i2dest as a scratch register with a | ||||||
4127 | different mode, substitute it for the original | ||||||
4128 | i2src while its original mode is temporarily | ||||||
4129 | restored, and then clear i2scratch so that we don't | ||||||
4130 | do it again later. */ | ||||||
4131 | propagate_for_debug (i2, last_combined_insn, reg, i2src, | ||||||
4132 | this_basic_block); | ||||||
4133 | i2scratch = false; | ||||||
4134 | /* Put back the new mode. */ | ||||||
4135 | adjust_reg_mode (reg, new_mode); | ||||||
4136 | } | ||||||
4137 | else | ||||||
4138 | { | ||||||
4139 | rtx tempreg = gen_raw_REG (old_mode, REGNO (reg)(rhs_regno(reg))); | ||||||
4140 | rtx_insn *first, *last; | ||||||
4141 | |||||||
4142 | if (reg == i2dest) | ||||||
4143 | { | ||||||
4144 | first = i2; | ||||||
4145 | last = last_combined_insn; | ||||||
4146 | } | ||||||
4147 | else | ||||||
4148 | { | ||||||
4149 | first = i3; | ||||||
4150 | last = undobuf.other_insn; | ||||||
4151 | gcc_assert (last)((void)(!(last) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/combine.cc" , 4151, __FUNCTION__), 0 : 0)); | ||||||
4152 | if (DF_INSN_LUID (last)((((df->insns[(INSN_UID (last))]))->luid)) | ||||||
4153 | < DF_INSN_LUID (last_combined_insn)((((df->insns[(INSN_UID (last_combined_insn))]))->luid) )) | ||||||
4154 | last = last_combined_insn; | ||||||
4155 | } | ||||||
4156 | |||||||
4157 | /* We're dealing with a reg that changed mode but not | ||||||
4158 | meaning, so we want to turn it into a subreg for | ||||||
4159 | the new mode. However, because of REG sharing and | ||||||
4160 | because its mode had already changed, we have to do | ||||||
4161 | it in two steps. First, replace any debug uses of | ||||||
4162 | reg, with its original mode temporarily restored, | ||||||
4163 | with this copy we have created; then, replace the | ||||||
4164 | copy with the SUBREG of the original shared reg, | ||||||
4165 | once again changed to the new mode. */ | ||||||
4166 | propagate_for_debug (first, last, reg, tempreg, | ||||||
4167 | this_basic_block); | ||||||
4168 | adjust_reg_mode (reg, new_mode); | ||||||
4169 | propagate_for_debug (first, last, tempreg, | ||||||
4170 | lowpart_subreg (old_mode, reg, new_mode), | ||||||
4171 | this_basic_block); | ||||||
4172 | } | ||||||
4173 | } | ||||||
4174 | } | ||||||
4175 | |||||||
4176 | /* If we will be able to accept this, we have made a | ||||||
4177 | change to the destination of I3. This requires us to | ||||||
4178 | do a few adjustments. */ | ||||||
4179 | |||||||
4180 | if (changed_i3_dest
| ||||||
4181 | { | ||||||
4182 | PATTERN (i3) = newpat; | ||||||
4183 | adjust_for_new_dest (i3); | ||||||
4184 | } | ||||||
4185 | |||||||
4186 | /* We now know that we can do this combination. Merge the insns and | ||||||
4187 | update the status of registers and LOG_LINKS. */ | ||||||
4188 | |||||||
4189 | if (undobuf.other_insn
| ||||||
4190 | { | ||||||
4191 | rtx note, next; | ||||||
4192 | |||||||
4193 | PATTERN (undobuf.other_insn) = other_pat; | ||||||
4194 | |||||||
4195 | /* If any of the notes in OTHER_INSN were REG_DEAD or REG_UNUSED, | ||||||
4196 | ensure that they are still valid. Then add any non-duplicate | ||||||
4197 | notes added by recog_for_combine. */ | ||||||
4198 | for (note = REG_NOTES (undobuf.other_insn)(((undobuf.other_insn)->u.fld[6]).rt_rtx); note; note = next) | ||||||
4199 | { | ||||||
4200 | next = XEXP (note, 1)(((note)->u.fld[1]).rt_rtx); | ||||||
4201 | |||||||
4202 | if ((REG_NOTE_KIND (note)((enum reg_note) ((machine_mode) (note)->mode)) == REG_DEAD | ||||||
4203 | && !reg_referenced_p (XEXP (note, 0)(((note)->u.fld[0]).rt_rtx), | ||||||
4204 | PATTERN (undobuf.other_insn))) | ||||||
4205 | ||(REG_NOTE_KIND (note)((enum reg_note) ((machine_mode) (note)->mode)) == REG_UNUSED | ||||||
4206 | && !reg_set_p (XEXP (note, 0)(((note)->u.fld[0]).rt_rtx), | ||||||
4207 | PATTERN (undobuf.other_insn))) | ||||||
4208 | /* Simply drop equal note since it may be no longer valid | ||||||
4209 | for other_insn. It may be possible to record that CC | ||||||
4210 | register is changed and only discard those notes, but | ||||||
4211 | in practice it's unnecessary complication and doesn't | ||||||
4212 | give any meaningful improvement. | ||||||
4213 | |||||||
4214 | See PR78559. */ | ||||||
4215 | || REG_NOTE_KIND (note)((enum reg_note) ((machine_mode) (note)->mode)) == REG_EQUAL | ||||||
4216 | || REG_NOTE_KIND (note)((enum reg_note) ((machine_mode) (note)->mode)) == REG_EQUIV) | ||||||
4217 | remove_note (undobuf.other_insn, note); | ||||||
4218 | } | ||||||
4219 | |||||||
4220 | distribute_notes (new_other_notes, undobuf.other_insn, | ||||||
4221 | undobuf.other_insn, NULLnullptr, NULL_RTX(rtx) 0, NULL_RTX(rtx) 0, | ||||||
4222 | NULL_RTX(rtx) 0); | ||||||
4223 | } | ||||||
4224 | |||||||
4225 | if (swap_i2i3
| ||||||
4226 | { | ||||||
4227 | /* I3 now uses what used to be its destination and which is now | ||||||
4228 | I2's destination. This requires us to do a few adjustments. */ | ||||||
4229 | PATTERN (i3) = newpat; | ||||||
4230 | adjust_for_new_dest (i3); | ||||||
4231 | } | ||||||
4232 | |||||||
4233 | if (swap_i2i3
| ||||||
4234 | { | ||||||
4235 | /* We might need a LOG_LINK from I3 to I2. But then we used to | ||||||
4236 | have one, so we still will. | ||||||
4237 | |||||||
4238 | However, some later insn might be using I2's dest and have | ||||||
4239 | a LOG_LINK pointing at I3. We should change it to point at | ||||||
4240 | I2 instead. */ | ||||||
4241 | |||||||
4242 | /* newi2pat is usually a SET here; however, recog_for_combine might | ||||||
4243 | have added some clobbers. */ | ||||||
4244 | rtx x = newi2pat; | ||||||
4245 | if (GET_CODE (x)((enum rtx_code) (x)->code) == PARALLEL) | ||||||
4246 | x = XVECEXP (newi2pat, 0, 0)(((((newi2pat)->u.fld[0]).rt_rtvec))->elem[0]); | ||||||
4247 | |||||||
4248 | if (REG_P (SET_DEST (x))(((enum rtx_code) ((((x)->u.fld[0]).rt_rtx))->code) == REG ) | ||||||
4249 | || (GET_CODE (SET_DEST (x))((enum rtx_code) ((((x)->u.fld[0]).rt_rtx))->code) == SUBREG | ||||||
4250 | && REG_P (SUBREG_REG (SET_DEST (x)))(((enum rtx_code) (((((((x)->u.fld[0]).rt_rtx))->u.fld[ 0]).rt_rtx))->code) == REG))) | ||||||
4251 | { | ||||||
4252 | unsigned int regno = reg_or_subregno (SET_DEST (x)(((x)->u.fld[0]).rt_rtx)); | ||||||
4253 | |||||||
4254 | bool done = false; | ||||||
4255 | for (rtx_insn *insn = NEXT_INSN (i3); | ||||||
4256 | !done | ||||||
4257 | && insn | ||||||
4258 | && INSN_P (insn)(((((enum rtx_code) (insn)->code) == INSN) || (((enum rtx_code ) (insn)->code) == JUMP_INSN) || (((enum rtx_code) (insn)-> code) == CALL_INSN)) || (((enum rtx_code) (insn)->code) == DEBUG_INSN)) | ||||||
4259 | && BLOCK_FOR_INSN (insn) == this_basic_block; | ||||||
4260 | insn = NEXT_INSN (insn)) | ||||||
4261 | { | ||||||
4262 | if (DEBUG_INSN_P (insn)(((enum rtx_code) (insn)->code) == DEBUG_INSN)) | ||||||
4263 | continue; | ||||||
4264 | struct insn_link *link; | ||||||
4265 | FOR_EACH_LOG_LINK (link, insn)for ((link) = (uid_log_links[insn_uid_check (insn)]); (link); (link) = (link)->next) | ||||||
4266 | if (link->insn == i3 && link->regno == regno) | ||||||
4267 | { | ||||||
4268 | link->insn = i2; | ||||||
4269 | done = true; | ||||||
4270 | break; | ||||||
4271 | } | ||||||
4272 | } | ||||||
4273 | } | ||||||
4274 | } | ||||||
4275 | |||||||
4276 | { | ||||||
4277 | rtx i3notes, i2notes, i1notes = 0, i0notes = 0; | ||||||
4278 | struct insn_link *i3links, *i2links, *i1links = 0, *i0links = 0; | ||||||
4279 | rtx midnotes = 0; | ||||||
4280 | int from_luid; | ||||||
4281 | /* Compute which registers we expect to eliminate. newi2pat may be setting | ||||||
4282 | either i3dest or i2dest, so we must check it. */ | ||||||
4283 | rtx elim_i2 = ((newi2pat
| ||||||
4284 | || i2dest_in_i2src || i2dest_in_i1src
|
75.2 | 'i2dest_in_i0src' is 0 |
77.1 | 'i1' is equal to null |
77.2 | 'local_elim_i1' is equal to null |
77.3 | 'i0' is equal to null |
77.4 | 'local_elim_i0' is equal to null |
77.5 | 'i1' is null |
78.1 | 'i0' is null |
84.1 | Field 'other_insn' is null |
85.1 | 'i3_subst_into_i2' is 0 |
88.1 | 'i1' is null |
89.1 | 'i0' is null |
90.1 | 'i0' is null |
91.1 | 'i1' is null |
92.1 | 'newi2pat' is null |
101.1 | 'midnotes' is null |
101.2 | 'newi2pat' is null |
102 | Branch condition evaluates to a garbage value |