Line data Source code
1 : /* RTL dead zero/sign extension (code) elimination.
2 : Copyright (C) 2000-2026 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 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "backend.h"
24 : #include "rtl.h"
25 : #include "tree.h"
26 : #include "memmodel.h"
27 : #include "insn-config.h"
28 : #include "emit-rtl.h"
29 : #include "expr.h"
30 : #include "recog.h"
31 : #include "cfganal.h"
32 : #include "tree-pass.h"
33 : #include "cfgrtl.h"
34 : #include "rtl-iter.h"
35 : #include "df.h"
36 : #include "print-rtl.h"
37 : #include "dbgcnt.h"
38 : #include "diagnostic-core.h"
39 : #include "target.h"
40 :
41 : /* These should probably move into a C++ class. */
42 : static vec<bitmap_head> livein;
43 : static bitmap all_blocks;
44 : static bitmap livenow;
45 : static bitmap changed_pseudos;
46 : static bool modify;
47 :
48 : /* Chain detection for promotion: we defer promotions and only apply them
49 : when they form chains (one candidate's result feeds another's operand).
50 : Standalone promotions are skipped as they cause regressions on targets
51 : with free sign extension (e.g., RISC-V W-suffix instructions). */
52 : struct promotion_candidate_info {
53 : rtx_insn *insn;
54 : rtx set;
55 : };
56 :
57 : static vec<promotion_candidate_info> promotion_candidates;
58 : static bitmap promotable_dests;
59 : static bitmap consumed_by_candidate;
60 :
61 : /* Copy pairs seen during the reverse scan (from optimized extensions).
62 : Used to propagate chain info transitively. */
63 : struct copy_info {
64 : unsigned int dest_regno;
65 : unsigned int src_regno;
66 : };
67 : static vec<copy_info> promotion_copies;
68 :
69 : /* We consider four bit groups for liveness:
70 : bit 0..7 (least significant byte)
71 : bit 8..15 (second least significant byte)
72 : bit 16..31
73 : bit 32..BITS_PER_WORD-1 */
74 :
75 : /* For the given REG, return the number of bit groups implied by the
76 : size of the REG's mode, up to a maximum of 4 (number of bit groups
77 : tracked by this pass).
78 :
79 : For partial integer and variable sized modes also return 4. This
80 : could possibly be refined for something like PSI mode, but it
81 : does not seem worth the effort. */
82 :
83 : static int
84 239792236 : group_limit (const_rtx reg)
85 : {
86 239792236 : machine_mode mode = GET_MODE (reg);
87 :
88 239792236 : if (!GET_MODE_BITSIZE (mode).is_constant ())
89 : return 4;
90 :
91 239792236 : int size = GET_MODE_SIZE (mode).to_constant ();
92 :
93 239792236 : size = exact_log2 (size);
94 :
95 239697873 : if (size < 0)
96 : return 4;
97 :
98 239697873 : size++;
99 239697873 : return (size > 4 ? 4 : size);
100 : }
101 :
102 : /* Make all bit groups live for REGNO in bitmap BMAP. For hard regs,
103 : we assume all groups are live. For a pseudo we consider the size
104 : of the pseudo to avoid creating unnecessarily live chunks of data. */
105 :
106 : static void
107 4810232 : make_reg_live (bitmap bmap, int regno)
108 : {
109 4810232 : int limit;
110 :
111 : /* For pseudos we can use the mode to limit how many bit groups
112 : are marked as live since a pseudo only has one mode. Hard
113 : registers have to be handled more conservatively. */
114 4810232 : if (regno > FIRST_PSEUDO_REGISTER)
115 : {
116 915977 : rtx reg = regno_reg_rtx[regno];
117 915977 : limit = group_limit (reg);
118 : }
119 : else
120 : limit = 4;
121 :
122 23717912 : for (int i = 0; i < limit; i++)
123 18907680 : bitmap_set_bit (bmap, regno * 4 + i);
124 4810232 : }
125 :
126 : /* Note this pass could be used to narrow memory loads too. It's
127 : not clear if that's profitable or not in general. */
128 :
129 : #define UNSPEC_P(X) (GET_CODE (X) == UNSPEC || GET_CODE (X) == UNSPEC_VOLATILE)
130 :
131 : /* If we know the destination of CODE only uses some low bits
132 : (say just the QI bits of an SI operation), then return true
133 : if we can propagate the need for just the subset of bits
134 : from the destination to the sources.
135 :
136 : FIXME: This is safe for operands 1 and 2 of an IF_THEN_ELSE, but not
137 : operand 0. Thus is likely would need some special casing to handle. */
138 :
139 : static bool
140 145724946 : safe_for_live_propagation (rtx_code code)
141 : {
142 : /* First handle rtx classes which as a whole are known to
143 : be either safe or unsafe. */
144 145724946 : switch (GET_RTX_CLASS (code))
145 : {
146 : case RTX_OBJ:
147 : case RTX_CONST_OBJ:
148 : return true;
149 :
150 : case RTX_COMPARE:
151 : case RTX_COMM_COMPARE:
152 : case RTX_TERNARY:
153 : return false;
154 :
155 75312072 : default:
156 75312072 : break;
157 : }
158 :
159 : /* What's left are specific codes. We only need to identify those
160 : which are safe. */
161 75312072 : switch (code)
162 : {
163 : /* These are trivially safe. */
164 : case SUBREG:
165 : case NOT:
166 : case ZERO_EXTEND:
167 : case SIGN_EXTEND:
168 : case TRUNCATE:
169 : case PLUS:
170 : case MINUS:
171 : case MULT:
172 : case SMUL_HIGHPART:
173 : case UMUL_HIGHPART:
174 : case AND:
175 : case IOR:
176 : case XOR:
177 : return true;
178 :
179 : /* We can propagate for the shifted operand, but not the shift
180 : count. The count is handled specially. */
181 : case ASHIFT:
182 : case LSHIFTRT:
183 : case ASHIFTRT:
184 : case SS_ASHIFT:
185 : case US_ASHIFT:
186 : return true;
187 :
188 : /* There may be other safe codes. If so they can be added
189 : individually when discovered. */
190 : default:
191 : return false;
192 : }
193 : }
194 :
195 : /* Clear bits in LIVENOW and set bits in LIVE_TMP for objects
196 : set/clobbered by OBJ contained in INSN.
197 :
198 : Conceptually it is always safe to ignore a particular destination
199 : here as that will result in more chunks of data being considered
200 : live. That's what happens when we "continue" the main loop when
201 : we see something we don't know how to handle such as a vector
202 : mode destination.
203 :
204 : The more accurate we are in identifying what objects (and chunks
205 : within an object) are set by INSN, the more aggressive the
206 : optimization phase during use handling will be. */
207 :
208 : static bool
209 140964819 : ext_dce_process_sets (rtx_insn *insn, rtx obj, bitmap live_tmp)
210 : {
211 140964819 : bool skipped_dest = false;
212 :
213 140964819 : subrtx_iterator::array_type array;
214 404229610 : FOR_EACH_SUBRTX (iter, array, obj, NONCONST)
215 : {
216 263264791 : const_rtx x = *iter;
217 :
218 : /* An EXPR_LIST (from call fusage) ends in NULL_RTX. */
219 263264791 : if (x == NULL_RTX)
220 9773325 : continue;
221 :
222 253491466 : if (UNSPEC_P (x))
223 570787 : continue;
224 :
225 252920679 : if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
226 : {
227 145748718 : unsigned bit = 0;
228 145748718 : x = SET_DEST (x);
229 :
230 : /* We don't support vector destinations or destinations
231 : wider than DImode. */
232 145748718 : scalar_mode outer_mode;
233 148955251 : if (!is_a <scalar_mode> (GET_MODE (x), &outer_mode)
234 92229418 : || GET_MODE_BITSIZE (outer_mode) > HOST_BITS_PER_WIDE_INT)
235 : {
236 : /* Skip the subrtxs of this destination. There is
237 : little value in iterating into the subobjects, so
238 : just skip them for a bit of efficiency. */
239 56725833 : skipped_dest = true;
240 56725833 : iter.skip_subrtxes ();
241 263264791 : continue;
242 : }
243 :
244 : /* We could have (strict_low_part (subreg ...)). We can not just
245 : strip the STRICT_LOW_PART as that would result in clearing
246 : some bits in LIVENOW that are still live. So process the
247 : STRICT_LOW_PART specially. */
248 89022885 : if (GET_CODE (x) == STRICT_LOW_PART)
249 : {
250 0 : x = XEXP (x, 0);
251 :
252 : /* The only valid operand of a STRICT_LOW_PART is a non
253 : paradoxical SUBREG. */
254 0 : gcc_assert (SUBREG_P (x)
255 : && !paradoxical_subreg_p (x)
256 : && SUBREG_BYTE (x).is_constant ());
257 :
258 : /* I think we should always see a REG here. But let's
259 : be sure. */
260 0 : gcc_assert (REG_P (SUBREG_REG (x)));
261 :
262 : /* The inner mode might be larger, just punt for
263 : that case. Remember, we can not just continue to process
264 : the inner RTXs due to the STRICT_LOW_PART. */
265 0 : if (!is_a <scalar_mode> (GET_MODE (SUBREG_REG (x)), &outer_mode)
266 0 : || GET_MODE_BITSIZE (outer_mode) > HOST_BITS_PER_WIDE_INT)
267 : {
268 : /* Skip the subrtxs of the STRICT_LOW_PART. We can't
269 : process them because it'll set objects as no longer
270 : live when they are in fact still live. */
271 0 : skipped_dest = true;
272 0 : iter.skip_subrtxes ();
273 0 : continue;
274 : }
275 :
276 : /* LIVE_TMP contains the set groups that are live-out and set in
277 : this insn. It is used to narrow the groups live-in for the
278 : inputs of this insn.
279 :
280 : The simple thing to do is mark all the groups as live, but
281 : that will significantly inhibit optimization.
282 :
283 : We also need to be careful in the case where we have an in-out
284 : operand. If we're not careful we'd clear LIVE_TMP
285 : incorrectly. */
286 0 : HOST_WIDE_INT rn = REGNO (SUBREG_REG (x));
287 0 : int limit = group_limit (SUBREG_REG (x));
288 0 : for (HOST_WIDE_INT i = 4 * rn; i < 4 * rn + limit; i++)
289 0 : if (bitmap_bit_p (livenow, i))
290 0 : bitmap_set_bit (live_tmp, i);
291 :
292 0 : if (bitmap_empty_p (live_tmp))
293 0 : make_reg_live (live_tmp, rn);
294 :
295 : /* The mode of the SUBREG tells us how many bits we can
296 : clear. */
297 0 : machine_mode mode = GET_MODE (x);
298 0 : HOST_WIDE_INT size
299 0 : = exact_log2 (GET_MODE_SIZE (mode).to_constant ()) + 1;
300 0 : bitmap_clear_range (livenow, 4 * rn, size);
301 :
302 : /* We have fully processed this destination. */
303 0 : iter.skip_subrtxes ();
304 0 : continue;
305 0 : }
306 :
307 : /* Phase one of destination handling. First remove any wrapper
308 : such as SUBREG or ZERO_EXTRACT. */
309 89022885 : unsigned HOST_WIDE_INT mask
310 89022885 : = GET_MODE_MASK (GET_MODE_INNER (GET_MODE (x)));
311 89022885 : if (SUBREG_P (x))
312 : {
313 : /* If we have a SUBREG destination that is too wide, just
314 : skip the destination rather than continuing this iterator.
315 : While continuing would be better, we'd need to strip the
316 : subreg and restart within the SET processing rather than
317 : the top of the loop which just complicates the flow even
318 : more. */
319 587107 : if (!is_a <scalar_mode> (GET_MODE (SUBREG_REG (x)), &outer_mode)
320 587107 : || GET_MODE_BITSIZE (outer_mode) > HOST_BITS_PER_WIDE_INT)
321 : {
322 141556 : skipped_dest = true;
323 141556 : iter.skip_subrtxes ();
324 141556 : continue;
325 : }
326 :
327 : /* We can safely strip a paradoxical subreg. The inner mode will
328 : be narrower than the outer mode. We'll clear fewer bits in
329 : LIVENOW than we'd like, but that's always safe. */
330 445551 : if (paradoxical_subreg_p (x))
331 : x = XEXP (x, 0);
332 435210 : else if (SUBREG_BYTE (x).is_constant ())
333 : {
334 435210 : bit = subreg_lsb (x).to_constant ();
335 435210 : mask = GET_MODE_MASK (GET_MODE (SUBREG_REG (x))) << bit;
336 435210 : gcc_assert (mask);
337 : x = SUBREG_REG (x);
338 : }
339 : else
340 : gcc_unreachable ();
341 : }
342 :
343 88881329 : if (GET_CODE (x) == ZERO_EXTRACT)
344 : {
345 : /* Unlike a SUBREG destination, a set of a ZERO_EXTRACT only
346 : modifies the bits referenced in the ZERO_EXTRACT, the rest
347 : remain the same. Thus we can not continue here, we must
348 : either figure out what part of the destination is modified
349 : or skip the sub-rtxs. */
350 3604 : skipped_dest = true;
351 3604 : iter.skip_subrtxes ();
352 3604 : continue;
353 : }
354 :
355 : /* BIT >= 64 indicates something went horribly wrong. */
356 88877725 : gcc_assert (bit <= HOST_BITS_PER_WIDE_INT - 1);
357 :
358 : /* Now handle the actual object that was changed. */
359 88877725 : if (REG_P (x))
360 : {
361 : /* LIVE_TMP contains the set groups that are live-out and set in
362 : this insn. It is used to narrow the groups live-in for the
363 : inputs of this insn.
364 :
365 : The simple thing to do is mark all the groups as live, but
366 : that will significantly inhibit optimization.
367 :
368 : We also need to be careful in the case where we have an in-out
369 : operand. If we're not careful we'd clear LIVE_TMP
370 : incorrectly. */
371 74611478 : HOST_WIDE_INT rn = REGNO (x);
372 74611478 : int limit = group_limit (x);
373 333834851 : for (HOST_WIDE_INT i = 4 * rn; i < 4 * rn + limit; i++)
374 259223373 : if (bitmap_bit_p (livenow, i))
375 251571595 : bitmap_set_bit (live_tmp, i);
376 :
377 74611478 : if (bitmap_empty_p (live_tmp))
378 1277705 : make_reg_live (live_tmp, rn);
379 :
380 : /* Now clear the bits known written by this instruction.
381 : Note that BIT need not be a power of two, consider a
382 : ZERO_EXTRACT destination. */
383 74611478 : int start = (bit < 8 ? 0 : bit < 16 ? 1 : bit < 32 ? 2 : 3);
384 79638764 : int end = ((mask & ~HOST_WIDE_INT_UC (0xffffffff)) ? 4
385 28322258 : : (mask & HOST_WIDE_INT_UC (0xffff0000)) ? 3
386 5858195 : : (mask & 0xff00) ? 2 : 1);
387 74611478 : bitmap_clear_range (livenow, 4 * rn + start, end - start);
388 : }
389 : /* Some ports generate (clobber (const_int)). */
390 14266247 : else if (CONST_INT_P (x))
391 0 : continue;
392 : else
393 14266247 : gcc_assert (CALL_P (insn)
394 : || MEM_P (x)
395 : || x == pc_rtx
396 : || GET_CODE (x) == SCRATCH);
397 :
398 88877725 : iter.skip_subrtxes ();
399 88877725 : }
400 107171961 : else if (GET_CODE (x) == COND_EXEC)
401 : {
402 : /* This isn't ideal, but may not be so bad in practice. */
403 0 : skipped_dest = true;
404 0 : iter.skip_subrtxes ();
405 : }
406 : }
407 140964819 : return skipped_dest;
408 140964819 : }
409 :
410 : /* INSN is a right shift and the second insn in a shift pair that is a
411 : sign or zero extension (SET is the single set associated with INSN).
412 :
413 : Replace the source of SET with NEW_SRC which is a source register
414 : from NEW_SRC_INSN (the left shift in the pair). This is effectively
415 : the same as the replacement we do for ZERO/SIGN extends on targets
416 : that support those insns. */
417 : static void
418 0 : ext_dce_try_optimize_rshift (rtx_insn *insn, rtx set, rtx new_src, rtx_insn *new_src_insn)
419 : {
420 : /* If the modes are not the same or one is a hard register, then
421 : conservatively do nothing. */
422 0 : if (GET_MODE (SET_SRC (set)) != GET_MODE (new_src)
423 0 : || !REG_P (XEXP (SET_SRC (set), 0))
424 0 : || !REG_P (new_src)
425 0 : || REGNO (XEXP (SET_SRC (set), 0)) < FIRST_PSEUDO_REGISTER
426 0 : || REGNO (new_src) < FIRST_PSEUDO_REGISTER)
427 : return;
428 :
429 0 : if (dump_file)
430 : {
431 0 : fprintf (dump_file, "Processing insn:\n");
432 0 : dump_insn_slim (dump_file, insn);
433 0 : fprintf (dump_file, "Trying to simplify pattern:\n");
434 0 : print_rtl_single (dump_file, SET_SRC (set));
435 : }
436 :
437 : /* We decided to turn do the optimization but allow it to be rejected for
438 : bisection purposes. */
439 0 : if (!dbg_cnt (::ext_dce))
440 : {
441 0 : if (dump_file)
442 0 : fprintf (dump_file, "Rejected due to debug counter.\n");
443 : return;
444 : }
445 :
446 : /* We're going to generate a fresh insn for the move, so put it
447 : into a sequence that we can emit after the current insn. */
448 0 : start_sequence ();
449 0 : emit_move_insn (SET_DEST (set), new_src);
450 0 : rtx_insn *seq = end_sequence ();
451 0 : emit_insn_after (seq, insn);
452 :
453 : /* Mark the destination as changed. */
454 0 : rtx x = SET_DEST (set);
455 0 : while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
456 0 : x = XEXP (x, 0);
457 0 : gcc_assert (REG_P (x));
458 0 : bitmap_set_bit (changed_pseudos, REGNO (x));
459 :
460 0 : if (dump_file)
461 : {
462 0 : fprintf (dump_file, "Successfully transformed to:\n");
463 0 : print_rtl_single (dump_file, PATTERN (seq));
464 0 : fprintf (dump_file, "\n");
465 : }
466 :
467 0 : delete_insn (insn);
468 :
469 : /* If NEW_SRC died in its prior location, then we need to remove the
470 : death note and move it to the new location. */
471 0 : rtx note = find_regno_note (new_src_insn, REG_DEAD, REGNO (new_src));
472 0 : if (note)
473 : {
474 0 : remove_note (new_src_insn, note);
475 0 : add_reg_note (insn, REG_DEAD, new_src);
476 : }
477 : }
478 :
479 :
480 : /* INSN has a sign/zero extended source inside SET that we will
481 : try to turn into a SUBREG. If NEW_SRC is non-null, use that
482 : for the new source of INSN's set. That scenario only happens
483 : when we're optimizing a shift pair. */
484 : static void
485 8885 : ext_dce_try_optimize_extension (rtx_insn *insn, rtx set)
486 : {
487 8885 : rtx src = SET_SRC (set);
488 8885 : rtx inner = XEXP (src, 0);
489 :
490 : /* For sign-extending loads from memory, try to replace with a
491 : zero-extending load when the upper bits are dead. E.g. on RISC-V
492 : this turns lh+zext.h into just lhu. */
493 8885 : if (MEM_P (inner) && GET_CODE (src) == SIGN_EXTEND)
494 : {
495 36 : if (dump_file)
496 : {
497 0 : fprintf (dump_file, "Processing insn:\n");
498 0 : dump_insn_slim (dump_file, insn);
499 0 : fprintf (dump_file, "Trying to narrow sign_extend to zero_extend:\n");
500 0 : print_rtl_single (dump_file, SET_SRC (set));
501 : }
502 :
503 36 : if (!dbg_cnt (::ext_dce))
504 : {
505 0 : if (dump_file)
506 0 : fprintf (dump_file, "Rejected due to debug counter.\n");
507 : return;
508 : }
509 :
510 36 : rtx new_pattern = gen_rtx_ZERO_EXTEND (GET_MODE (src), inner);
511 36 : int ok = validate_change (insn, &SET_SRC (set), new_pattern, false);
512 :
513 36 : rtx x = SET_DEST (set);
514 36 : while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
515 0 : x = XEXP (x, 0);
516 :
517 36 : gcc_assert (REG_P (x));
518 36 : if (ok)
519 : {
520 36 : bitmap_set_bit (changed_pseudos, REGNO (x));
521 36 : remove_reg_equal_equiv_notes (insn, false);
522 : }
523 :
524 36 : if (dump_file)
525 : {
526 0 : if (ok)
527 0 : fprintf (dump_file, "Successfully transformed to:\n");
528 : else
529 0 : fprintf (dump_file, "Failed transformation to:\n");
530 0 : print_rtl_single (dump_file, new_pattern);
531 0 : fprintf (dump_file, "\n");
532 : }
533 : return;
534 : }
535 :
536 : /* Avoid (subreg (mem)) and other constructs which may be valid RTL, but
537 : not useful for this optimization. */
538 8849 : if (!(REG_P (inner) || (SUBREG_P (inner) && REG_P (SUBREG_REG (inner)))))
539 : return;
540 :
541 5980 : rtx new_pattern;
542 5980 : if (dump_file)
543 : {
544 0 : fprintf (dump_file, "Processing insn:\n");
545 0 : dump_insn_slim (dump_file, insn);
546 0 : fprintf (dump_file, "Trying to simplify pattern:\n");
547 0 : print_rtl_single (dump_file, SET_SRC (set));
548 : }
549 :
550 : /* We decided to turn do the optimization but allow it to be rejected for
551 : bisection purposes. */
552 5980 : if (!dbg_cnt (::ext_dce))
553 : {
554 0 : if (dump_file)
555 0 : fprintf (dump_file, "Rejected due to debug counter.\n");
556 : return;
557 : }
558 :
559 11960 : new_pattern = simplify_gen_subreg (GET_MODE (src), inner,
560 5980 : GET_MODE (inner), 0);
561 : /* simplify_gen_subreg may fail in which case NEW_PATTERN will be NULL.
562 : We must not pass that as a replacement pattern to validate_change. */
563 5980 : if (new_pattern)
564 : {
565 5980 : int ok = validate_change (insn, &SET_SRC (set), new_pattern, false);
566 :
567 5980 : rtx x = SET_DEST (set);
568 5980 : while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
569 0 : x = XEXP (x, 0);
570 :
571 5980 : gcc_assert (REG_P (x));
572 5980 : if (ok)
573 5980 : bitmap_set_bit (changed_pseudos, REGNO (x));
574 :
575 5980 : if (dump_file)
576 : {
577 0 : if (ok)
578 0 : fprintf (dump_file, "Successfully transformed to:\n");
579 : else
580 0 : fprintf (dump_file, "Failed transformation to:\n");
581 :
582 0 : print_rtl_single (dump_file, new_pattern);
583 0 : fprintf (dump_file, "\n");
584 : }
585 :
586 : /* INSN may have a REG_EQUAL note indicating that the value was
587 : sign or zero extended. That note is no longer valid since we've
588 : just removed the extension. Just wipe the notes. */
589 5980 : if (ok)
590 5980 : remove_reg_equal_equiv_notes (insn, false);
591 : }
592 : else
593 : {
594 0 : if (dump_file)
595 0 : fprintf (dump_file, "Unable to generate valid SUBREG expression.\n");
596 : }
597 : }
598 :
599 : /* Try to promote a narrow-mode operation wrapped in a sign/zero extension
600 : to the wider mode when the extended bits are dead. For example,
601 : (sign_extend:DI (plus:SI (x) (y))) -> (plus:DI (x') (y'))
602 : where x' and y' are the operands promoted to DI mode.
603 :
604 : This enables the combine pass to match wider-mode target patterns
605 : (e.g., sh2add on RISC-V) that cannot match the narrow-mode operation. */
606 :
607 : static void
608 0 : ext_dce_try_promote_operation (rtx_insn *insn, rtx set)
609 : {
610 0 : rtx src = SET_SRC (set);
611 :
612 : /* If the extension was already optimized away, nothing to do. */
613 0 : if (GET_CODE (src) != SIGN_EXTEND && GET_CODE (src) != ZERO_EXTEND)
614 0 : return;
615 :
616 0 : machine_mode outer_mode = GET_MODE (src);
617 0 : rtx inner = XEXP (src, 0);
618 :
619 : /* Only handle binary and unary arithmetic/logic operations. */
620 0 : if (!BINARY_P (inner) && !UNARY_P (inner))
621 : return;
622 :
623 0 : rtx_code inner_code = GET_CODE (inner);
624 :
625 : /* Restrict to operations whose result in the low bits is identical
626 : regardless of input width (i.e., no high-bit dependencies). */
627 0 : switch (inner_code)
628 : {
629 0 : case PLUS:
630 0 : case MINUS:
631 0 : case MULT:
632 0 : case NEG:
633 0 : case AND:
634 0 : case IOR:
635 0 : case XOR:
636 0 : case NOT:
637 0 : case ASHIFT:
638 0 : break;
639 : default:
640 : return;
641 : }
642 :
643 : /* Promote each operand to the outer mode. */
644 0 : int nops = BINARY_P (inner) ? 2 : 1;
645 0 : rtx new_ops[2];
646 :
647 0 : for (int i = 0; i < nops; i++)
648 : {
649 0 : rtx op = XEXP (inner, i);
650 :
651 0 : if (CONST_INT_P (op))
652 0 : new_ops[i] = op;
653 0 : else if (REG_P (op))
654 : {
655 0 : new_ops[i] = simplify_gen_subreg (outer_mode, op,
656 0 : GET_MODE (op), 0);
657 0 : if (!new_ops[i])
658 : return;
659 : }
660 0 : else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
661 : {
662 : /* The inner register may already be in the target mode
663 : (e.g., subreg:SI (reg:DI ...) 0). Extract it directly
664 : rather than creating a paradoxical subreg of a subreg,
665 : which simplify_gen_subreg rejects. */
666 0 : rtx inner_reg = SUBREG_REG (op);
667 0 : if (GET_MODE (inner_reg) == outer_mode)
668 0 : new_ops[i] = inner_reg;
669 : else
670 : {
671 0 : new_ops[i] = simplify_gen_subreg (outer_mode, inner_reg,
672 : GET_MODE (inner_reg), 0);
673 0 : if (!new_ops[i])
674 : return;
675 : }
676 : }
677 : else
678 : return;
679 : }
680 :
681 : /* Build the promoted operation. */
682 0 : rtx new_src;
683 0 : if (BINARY_P (inner))
684 0 : new_src = gen_rtx_fmt_ee (inner_code, outer_mode,
685 : new_ops[0], new_ops[1]);
686 : else
687 0 : new_src = gen_rtx_fmt_e (inner_code, outer_mode, new_ops[0]);
688 :
689 0 : if (dump_file)
690 : {
691 0 : fprintf (dump_file, "Processing insn:\n");
692 0 : dump_insn_slim (dump_file, insn);
693 0 : fprintf (dump_file, "Trying to promote to wider mode:\n");
694 0 : print_rtl_single (dump_file, new_src);
695 : }
696 :
697 : /* We decided to try the promotion but allow it to be rejected for
698 : bisection purposes. */
699 0 : if (!dbg_cnt (::ext_dce))
700 : {
701 0 : if (dump_file)
702 0 : fprintf (dump_file, "Rejected due to debug counter.\n");
703 : return;
704 : }
705 :
706 0 : int ok = validate_change (insn, &SET_SRC (set), new_src, false);
707 :
708 0 : rtx x = SET_DEST (set);
709 0 : while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
710 0 : x = XEXP (x, 0);
711 :
712 0 : gcc_assert (REG_P (x));
713 0 : if (ok)
714 0 : bitmap_set_bit (changed_pseudos, REGNO (x));
715 :
716 0 : if (dump_file)
717 : {
718 0 : if (ok)
719 0 : fprintf (dump_file, "Successfully promoted to:\n");
720 : else
721 0 : fprintf (dump_file, "Failed promotion to:\n");
722 0 : print_rtl_single (dump_file, new_src);
723 0 : fprintf (dump_file, "\n");
724 : }
725 :
726 0 : if (ok)
727 0 : remove_reg_equal_equiv_notes (insn, false);
728 : }
729 :
730 : /* Record INSN as a promotion candidate if it passes the same validity
731 : checks as ext_dce_try_promote_operation. We defer actual promotion
732 : until we can determine whether the candidate is part of a chain. */
733 :
734 : static void
735 2905 : ext_dce_record_promotion_candidate (rtx_insn *insn, rtx set)
736 : {
737 2905 : rtx src = SET_SRC (set);
738 :
739 2905 : if (GET_CODE (src) != SIGN_EXTEND && GET_CODE (src) != ZERO_EXTEND)
740 : return;
741 :
742 2905 : machine_mode outer_mode = GET_MODE (src);
743 2905 : rtx inner = XEXP (src, 0);
744 :
745 2905 : if (!BINARY_P (inner) && !UNARY_P (inner))
746 : return;
747 :
748 1850 : rtx_code inner_code = GET_CODE (inner);
749 :
750 1850 : switch (inner_code)
751 : {
752 0 : case PLUS:
753 0 : case MINUS:
754 0 : case MULT:
755 0 : case NEG:
756 0 : case AND:
757 0 : case IOR:
758 0 : case XOR:
759 0 : case NOT:
760 0 : case ASHIFT:
761 0 : break;
762 : default:
763 : return;
764 : }
765 :
766 : /* Dry-run: check that all operands can be promoted. */
767 0 : int nops = BINARY_P (inner) ? 2 : 1;
768 0 : for (int i = 0; i < nops; i++)
769 : {
770 0 : rtx op = XEXP (inner, i);
771 0 : if (CONST_INT_P (op))
772 0 : continue;
773 0 : else if (REG_P (op))
774 : {
775 0 : if (!simplify_gen_subreg (outer_mode, op, GET_MODE (op), 0))
776 : return;
777 : }
778 0 : else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
779 : {
780 0 : rtx inner_reg = SUBREG_REG (op);
781 0 : if (GET_MODE (inner_reg) != outer_mode
782 0 : && !simplify_gen_subreg (outer_mode, inner_reg,
783 : GET_MODE (inner_reg), 0))
784 : return;
785 : }
786 : else
787 : return;
788 : }
789 :
790 : /* Find the destination register. */
791 0 : rtx dest = SET_DEST (set);
792 0 : while (SUBREG_P (dest) || GET_CODE (dest) == ZERO_EXTRACT)
793 0 : dest = XEXP (dest, 0);
794 0 : if (!REG_P (dest))
795 : return;
796 0 : unsigned int dest_regno = REGNO (dest);
797 :
798 : /* Record the candidate. */
799 0 : promotion_candidates.safe_push ({insn, set});
800 0 : bitmap_set_bit (promotable_dests, dest_regno);
801 :
802 : /* Mark register operands as consumed by a candidate. */
803 0 : for (int i = 0; i < nops; i++)
804 : {
805 0 : rtx op = XEXP (inner, i);
806 0 : if (REG_P (op))
807 0 : bitmap_set_bit (consumed_by_candidate, REGNO (op));
808 0 : else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
809 0 : bitmap_set_bit (consumed_by_candidate, REGNO (SUBREG_REG (op)));
810 : }
811 : }
812 :
813 : /* Promote candidates that form chains: a candidate whose result feeds
814 : into another candidate's operand, or whose operand comes from another
815 : candidate's result. Skip standalone (isolated) promotions. */
816 :
817 : static void
818 10027489 : ext_dce_promote_chained_candidates (void)
819 : {
820 : /* Propagate chain info through copies recorded during the reverse scan.
821 : Since copies are recorded in reverse order, iterate forward to propagate
822 : promotable_dests (which was set late in the scan) through copies that
823 : were seen earlier. */
824 10027489 : unsigned cix;
825 10027489 : copy_info *cp;
826 10033469 : FOR_EACH_VEC_ELT (promotion_copies, cix, cp)
827 : {
828 5980 : if (bitmap_bit_p (promotable_dests, cp->src_regno))
829 0 : bitmap_set_bit (promotable_dests, cp->dest_regno);
830 5980 : if (bitmap_bit_p (consumed_by_candidate, cp->dest_regno))
831 0 : bitmap_set_bit (consumed_by_candidate, cp->src_regno);
832 : }
833 :
834 : unsigned ix;
835 : promotion_candidate_info *cand;
836 :
837 10027489 : FOR_EACH_VEC_ELT (promotion_candidates, ix, cand)
838 : {
839 : /* Find destination register. */
840 0 : rtx dest = SET_DEST (cand->set);
841 0 : while (SUBREG_P (dest) || GET_CODE (dest) == ZERO_EXTRACT)
842 0 : dest = XEXP (dest, 0);
843 0 : unsigned int dest_regno = REGNO (dest);
844 :
845 : /* Check if this candidate's result feeds into another candidate. */
846 0 : bool is_chained = bitmap_bit_p (consumed_by_candidate, dest_regno);
847 :
848 : /* Check if any operand comes from another candidate's result. */
849 0 : if (!is_chained)
850 : {
851 0 : rtx inner = XEXP (SET_SRC (cand->set), 0);
852 0 : int nops = BINARY_P (inner) ? 2 : 1;
853 0 : for (int i = 0; i < nops && !is_chained; i++)
854 : {
855 0 : rtx op = XEXP (inner, i);
856 0 : if (REG_P (op))
857 0 : is_chained = bitmap_bit_p (promotable_dests, REGNO (op));
858 0 : else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
859 0 : is_chained = bitmap_bit_p (promotable_dests,
860 0 : REGNO (SUBREG_REG (op)));
861 : }
862 : }
863 :
864 0 : if (is_chained)
865 0 : ext_dce_try_promote_operation (cand->insn, cand->set);
866 0 : else if (dump_file)
867 : {
868 0 : fprintf (dump_file, "Skipping standalone promotion for insn:\n");
869 0 : dump_insn_slim (dump_file, cand->insn);
870 0 : fprintf (dump_file, "\n");
871 : }
872 : }
873 :
874 10027489 : promotion_candidates.truncate (0);
875 10027489 : promotion_copies.truncate (0);
876 10027489 : bitmap_clear (promotable_dests);
877 10027489 : bitmap_clear (consumed_by_candidate);
878 10027489 : }
879 :
880 : /* Some operators imply that their second operand is fully live,
881 : regardless of how many bits in the output are live. An example
882 : would be the shift count on a target without SHIFT_COUNT_TRUNCATED
883 : defined.
884 :
885 : Return TRUE if CODE is such an operator. FALSE otherwise. */
886 :
887 : static bool
888 78385162 : binop_implies_op2_fully_live (rtx_code code)
889 : {
890 0 : switch (code)
891 : {
892 : case ASHIFT:
893 : case LSHIFTRT:
894 : case ASHIFTRT:
895 : case ROTATE:
896 : case ROTATERT:
897 : case SS_ASHIFT:
898 : case US_ASHIFT:
899 : return !SHIFT_COUNT_TRUNCATED;
900 :
901 0 : default:
902 0 : return false;
903 : }
904 : }
905 :
906 : /* X, with code CODE, is an operation for which safe_for_live_propagation
907 : holds true, and bits set in MASK are live in the result. Compute a
908 : mask of (potentially) live bits in the non-constant inputs. In case of
909 : binop_implies_op2_fully_live (e.g. shifts), the computed mask may
910 : exclusively pertain to the first operand.
911 :
912 : This looks wrong as we may have some important operations embedded as
913 : operands of another operation. For example, we might have an extension
914 : wrapping a shift. It really feels like this needs to be recursing down
915 : into operands much more often. */
916 :
917 : unsigned HOST_WIDE_INT
918 73127003 : carry_backpropagate (unsigned HOST_WIDE_INT mask, enum rtx_code code, rtx x)
919 : {
920 74824991 : if (mask == 0)
921 : return 0;
922 :
923 : /* Consider a vector operation, the bits live are the element bits live
924 : broadcasted across the vector. So there can be holes (consider a
925 : logical shift).
926 :
927 : Vector modes aren't likely to represent cases we can optimize with
928 : any regularity. It seems sensible to just punt that case in a
929 : conservatively correct way.
930 :
931 : The conservatively corect choice here would be to return the mode
932 : mask for the outer mode. We're already doing that for modes larger
933 : than HOST_BITS_PER_WIDE_INT, so it should be safe for larger vectors
934 : as well as something like V2HI. */
935 74824937 : if (VECTOR_MODE_P (GET_MODE (x)) || COMPLEX_MODE_P (GET_MODE (x)))
936 4050899 : return GET_MODE_MASK (GET_MODE (x));
937 :
938 :
939 70774038 : enum machine_mode mode = GET_MODE (x);
940 70774038 : unsigned HOST_WIDE_INT mmask = GET_MODE_MASK (mode);
941 :
942 : /* While we don't try to optimize operations on types larger
943 : than 64 bits, we do want to make sure not to invoke undefined
944 : behavior when presented with such operations during use
945 : processing. The safe thing to do is to just return mmask
946 : for that scenario indicating every possible chunk is life. */
947 70774038 : scalar_int_mode smode;
948 70774038 : if (!is_a <scalar_int_mode> (mode, &smode)
949 59043531 : || GET_MODE_BITSIZE (smode) > HOST_BITS_PER_WIDE_INT)
950 : return mmask;
951 :
952 58075678 : switch (code)
953 : {
954 16383102 : case PLUS:
955 16383102 : case MINUS:
956 16383102 : case MULT:
957 16383102 : return (HOST_WIDE_INT_UC (2) << floor_log2 (mask)) - 1;
958 :
959 : /* We propagate for the shifted operand, but not the shift
960 : count. The count is handled specially. */
961 1395542 : case ASHIFT:
962 1395542 : if (CONST_INT_P (XEXP (x, 1))
963 2719903 : && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
964 1324333 : return (HOST_WIDE_INT) mask >> INTVAL (XEXP (x, 1));
965 71209 : return (HOST_WIDE_INT_UC (2) << floor_log2 (mask)) - 1;
966 :
967 : /* We propagate for the shifted operand, but not the shift
968 : count. The count is handled specially. */
969 616209 : case LSHIFTRT:
970 616209 : if (CONST_INT_P (XEXP (x, 1))
971 1201929 : && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
972 585692 : return mmask & (mask << INTVAL (XEXP (x, 1)));
973 : return mmask;
974 :
975 : /* We propagate for the shifted operand, but not the shift
976 : count. The count is handled specially. */
977 308554 : case ASHIFTRT:
978 308554 : if (CONST_INT_P (XEXP (x, 1))
979 602430 : && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
980 : {
981 293876 : HOST_WIDE_INT sign = 0;
982 293876 : if (HOST_BITS_PER_WIDE_INT - clz_hwi (mask) + INTVAL (XEXP (x, 1))
983 293876 : > GET_MODE_BITSIZE (smode))
984 587752 : sign = HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (smode) - 1);
985 293876 : return sign | (mmask & (mask << INTVAL (XEXP (x, 1))));
986 : }
987 : return mmask;
988 :
989 43529 : case SMUL_HIGHPART:
990 43529 : case UMUL_HIGHPART:
991 43529 : if (XEXP (x, 1) == const0_rtx)
992 : return 0;
993 43529 : if (XEXP (x, 1) == const1_rtx)
994 : return mmask;
995 43529 : if (CONST_INT_P (XEXP (x, 1)))
996 : {
997 0 : if (pow2p_hwi (INTVAL (XEXP (x, 1))))
998 0 : return mmask & (mask << (GET_MODE_BITSIZE (smode)
999 0 : - exact_log2 (INTVAL (XEXP (x, 1)))));
1000 :
1001 0 : int bits = (HOST_BITS_PER_WIDE_INT + GET_MODE_BITSIZE (smode)
1002 0 : - clz_hwi (mask) - ctz_hwi (INTVAL (XEXP (x, 1))));
1003 0 : if (bits < GET_MODE_BITSIZE (smode))
1004 0 : return (HOST_WIDE_INT_1U << bits) - 1;
1005 : }
1006 : return mmask;
1007 :
1008 574280 : case SIGN_EXTEND:
1009 574280 : if (!GET_MODE_BITSIZE (GET_MODE (x)).is_constant ()
1010 574280 : || !GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))).is_constant ())
1011 : return -1;
1012 :
1013 : /* See note about vector modes near the start of this function. */
1014 574280 : if (VECTOR_MODE_P (GET_MODE (XEXP (x, 0)))
1015 574280 : || COMPLEX_MODE_P (GET_MODE (XEXP (x, 0))))
1016 0 : return GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
1017 :
1018 : /* We want the mode of the inner object. We need to ensure its
1019 : sign bit is on in MASK. */
1020 574280 : mode = GET_MODE_INNER (GET_MODE (XEXP (x, 0)));
1021 574280 : if (mask & ~GET_MODE_MASK (mode))
1022 573755 : mask |= HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (mode).to_constant ()
1023 573755 : - 1);
1024 :
1025 : /* Recurse into the operand. */
1026 574280 : return carry_backpropagate (mask, GET_CODE (XEXP (x, 0)), XEXP (x, 0));
1027 :
1028 1123708 : case ZERO_EXTEND:
1029 1123708 : if (!GET_MODE_BITSIZE (GET_MODE (x)).is_constant ()
1030 1123708 : || !GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))).is_constant ())
1031 : return -1;
1032 :
1033 : /* Recurse into the operand. */
1034 1123708 : return carry_backpropagate (mask, GET_CODE (XEXP (x, 0)), XEXP (x, 0));
1035 :
1036 : /* If an AND/IOR unconditionally clears/sets bits in the output, then
1037 : we do not care about the liveness of those bits in the inputs.
1038 :
1039 : So AND MASK with the constant for AND and with the complemented constant
1040 : for IOR. */
1041 1343171 : case AND:
1042 1343171 : case IOR:
1043 1343171 : if (CONST_INT_P (XEXP (x, 1)))
1044 795240 : mask &= (code == AND
1045 795240 : ? UINTVAL (XEXP (x, 1))
1046 96737 : : ~UINTVAL (XEXP (x, 1)));
1047 : return mask;
1048 :
1049 : /* We propagate for the shifted operand, but not the shift
1050 : count. The count is handled specially. */
1051 0 : case SS_ASHIFT:
1052 0 : case US_ASHIFT:
1053 0 : if (CONST_INT_P (XEXP (x, 1))
1054 0 : && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
1055 : {
1056 0 : return ((mmask & ~((unsigned HOST_WIDE_INT) mmask
1057 0 : >> (INTVAL (XEXP (x, 1))
1058 0 : + (XEXP (x, 1) != const0_rtx
1059 0 : && code == SS_ASHIFT))))
1060 0 : | ((HOST_WIDE_INT) mask >> INTVAL (XEXP (x, 1))));
1061 : }
1062 : return mmask;
1063 :
1064 : default:
1065 : return mask;
1066 : }
1067 : }
1068 :
1069 : /* Process uses in INSN contained in OBJ. Set appropriate bits in LIVENOW
1070 : for any chunks of pseudos that become live, potentially filtering using
1071 : bits from LIVE_TMP.
1072 :
1073 : If MODIFY is true, then optimize sign/zero extensions to SUBREGs when
1074 : the extended bits are never read and mark pseudos which had extensions
1075 : eliminated in CHANGED_PSEUDOS. */
1076 :
1077 : static void
1078 140964819 : ext_dce_process_uses (rtx_insn *insn, rtx obj,
1079 : bitmap live_tmp, bool skipped_dest)
1080 : {
1081 140964819 : subrtx_var_iterator::array_type array_var;
1082 771372583 : FOR_EACH_SUBRTX_VAR (iter, array_var, obj, NONCONST)
1083 : {
1084 : /* An EXPR_LIST (from call fusage) ends in NULL_RTX. */
1085 630407764 : rtx x = *iter;
1086 630407764 : if (x == NULL_RTX)
1087 9773325 : continue;
1088 :
1089 : /* So the basic idea in this FOR_EACH_SUBRTX_VAR loop is to
1090 : handle SETs explicitly, possibly propagating live information
1091 : into the uses.
1092 :
1093 : We may continue the loop at various points which will cause
1094 : iteration into the next level of RTL. Breaking from the loop
1095 : is never safe as it can lead us to fail to process some of the
1096 : RTL and thus not make objects live when necessary. */
1097 620634439 : enum rtx_code xcode = GET_CODE (x);
1098 620634439 : if (xcode == SET)
1099 : {
1100 124623077 : const_rtx dst = SET_DEST (x);
1101 124623077 : rtx src = SET_SRC (x);
1102 124623077 : const_rtx y;
1103 124623077 : unsigned HOST_WIDE_INT bit = 0;
1104 :
1105 : /* The code of the RHS of a SET. */
1106 124623077 : enum rtx_code code = GET_CODE (src);
1107 :
1108 : /* ?!? How much of this should mirror SET handling, potentially
1109 : being shared? */
1110 124623077 : if (SUBREG_P (dst) && subreg_lsb (dst).is_constant (&bit))
1111 : {
1112 632305 : if (bit >= HOST_BITS_PER_WIDE_INT)
1113 : bit = HOST_BITS_PER_WIDE_INT - 1;
1114 632305 : dst = SUBREG_REG (dst);
1115 : }
1116 123990772 : else if (GET_CODE (dst) == STRICT_LOW_PART)
1117 10540 : dst = XEXP (dst, 0);
1118 :
1119 : /* Main processing of the uses. Two major goals here.
1120 :
1121 : First, we want to try and propagate liveness (or the lack
1122 : thereof) from the destination register to the source
1123 : register(s).
1124 :
1125 : Second, if the source is an extension, try to optimize
1126 : it into a SUBREG. The SUBREG form indicates we don't
1127 : care about the upper bits and will usually be copy
1128 : propagated away.
1129 :
1130 : If we fail to handle something in here, the expectation
1131 : is the iterator will dive into the sub-components and
1132 : mark all the chunks in any found REGs as live. */
1133 124623077 : if (REG_P (dst) && safe_for_live_propagation (code))
1134 : {
1135 : /* Create a mask representing the bits of this output
1136 : operand that are live after this insn. We can use
1137 : this information to refine the live in state of
1138 : inputs to this insn in many cases.
1139 :
1140 : We have to do this on a per SET basis, we might have
1141 : an INSN with multiple SETS, some of which can narrow
1142 : the source operand liveness, some of which may not. */
1143 73127003 : unsigned HOST_WIDE_INT dst_mask = 0;
1144 73127003 : HOST_WIDE_INT rn = REGNO (dst);
1145 73127003 : unsigned HOST_WIDE_INT mask_array[]
1146 : = { 0xff, 0xff00, HOST_WIDE_INT_UC (0xffff0000),
1147 : -HOST_WIDE_INT_UC (0x100000000) };
1148 365635015 : for (int i = 0; i < 4; i++)
1149 292508012 : if (bitmap_bit_p (live_tmp, 4 * rn + i))
1150 234935178 : dst_mask |= mask_array[i];
1151 73127003 : dst_mask >>= bit;
1152 :
1153 : /* If we ignored a destination during set processing, then
1154 : consider all the bits live. */
1155 73127003 : if (skipped_dest)
1156 25451576 : dst_mask = -1;
1157 :
1158 73127003 : dst_mask = carry_backpropagate (dst_mask, code, src);
1159 :
1160 : /* ??? Could also handle ZERO_EXTRACT / SIGN_EXTRACT
1161 : of the source specially to improve optimization. */
1162 73127003 : if (code == SIGN_EXTEND || code == ZERO_EXTEND)
1163 : {
1164 1725351 : rtx inner = XEXP (src, 0);
1165 1725351 : unsigned HOST_WIDE_INT src_mask
1166 1725351 : = GET_MODE_MASK (GET_MODE (inner));
1167 :
1168 : /* DST_MASK could be zero if we had something in the SET
1169 : that we couldn't handle. */
1170 1725351 : if (modify && !skipped_dest && (dst_mask & ~src_mask) == 0)
1171 : {
1172 8885 : ext_dce_try_optimize_extension (insn, x);
1173 :
1174 : /* If the extension was optimized to a copy, propagate
1175 : chain info through it: if the dest is consumed by a
1176 : promotion candidate (seen later in reverse scan),
1177 : the source register is transitively consumed too. */
1178 8885 : rtx opt_src = SET_SRC (x);
1179 8885 : if (GET_CODE (opt_src) != SIGN_EXTEND
1180 8885 : && GET_CODE (opt_src) != ZERO_EXTEND)
1181 : {
1182 5980 : rtx copy_dest = SET_DEST (x);
1183 5980 : while (SUBREG_P (copy_dest)
1184 5980 : || GET_CODE (copy_dest) == ZERO_EXTRACT)
1185 0 : copy_dest = XEXP (copy_dest, 0);
1186 :
1187 5980 : rtx copy_src = opt_src;
1188 5980 : if (SUBREG_P (copy_src))
1189 5653 : copy_src = SUBREG_REG (copy_src);
1190 :
1191 5980 : if (REG_P (copy_dest) && REG_P (copy_src))
1192 : {
1193 5980 : if (bitmap_bit_p (consumed_by_candidate,
1194 5980 : REGNO (copy_dest)))
1195 0 : bitmap_set_bit (consumed_by_candidate,
1196 0 : REGNO (copy_src));
1197 5980 : if (bitmap_bit_p (promotable_dests,
1198 5980 : REGNO (copy_src)))
1199 0 : bitmap_set_bit (promotable_dests,
1200 0 : REGNO (copy_dest));
1201 5980 : promotion_copies.safe_push (
1202 5980 : {REGNO (copy_dest), REGNO (copy_src)});
1203 : }
1204 : }
1205 : else
1206 2905 : ext_dce_record_promotion_candidate (insn, x);
1207 : }
1208 :
1209 : /* Stripping the extension here just seems wrong on multiple
1210 : levels. It's source side handling, so it seems like it
1211 : belongs in the loop below. Stripping here also makes it
1212 : harder than necessary to properly handle live bit groups
1213 : for (ANY_EXTEND (SUBREG)) where the SUBREG has
1214 : SUBREG_PROMOTED state. */
1215 1725351 : dst_mask &= src_mask;
1216 1725351 : src = XEXP (src, 0);
1217 1725351 : code = GET_CODE (src);
1218 : }
1219 :
1220 : /* Special case for (sub)targets that do not have extension
1221 : insns (and thus use shifts). We want to detect when we have
1222 : a shift pair and treat the pair as-if was an extension.
1223 :
1224 : Key on the right shift and use (for now) simplistic tests
1225 : to find the corresponding left shift. */
1226 73127003 : scalar_mode outer_mode;
1227 73127003 : if ((code == LSHIFTRT || code == ASHIFTRT)
1228 1087246 : && CONST_INT_P (XEXP (src, 1))
1229 1195267 : && (INTVAL (XEXP (src, 1)) == BITS_PER_WORD - 8
1230 1190953 : || INTVAL (XEXP (src, 1)) == BITS_PER_WORD - 16
1231 1024510 : || INTVAL (XEXP (src, 1)) == BITS_PER_WORD - 32)
1232 127416 : && is_a <scalar_mode> (GET_MODE (src), &outer_mode)
1233 74298944 : && GET_MODE_BITSIZE (outer_mode) <= HOST_BITS_PER_WIDE_INT)
1234 : {
1235 : /* So we have a right shift that could correspond to
1236 : the second in a pair implementing QI, HI or SI -> DI
1237 : extension. See if we can find the left shift. For
1238 : now, just look one real instruction back. */
1239 84695 : rtx_insn *prev_insn = prev_nonnote_nondebug_insn_bb (insn);
1240 :
1241 : /* The previous insn must be a left shift by the same
1242 : amount. */
1243 84695 : rtx prev_set;
1244 84695 : if (prev_insn
1245 82150 : && (prev_set = single_set (prev_insn))
1246 : /* The destination of the left shift must be the
1247 : source of the right shift. */
1248 82071 : && SET_DEST (prev_set) == XEXP (src, 0)
1249 45051 : && GET_CODE (SET_SRC (prev_set)) == ASHIFT
1250 655 : && CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
1251 : /* The counts must match. */
1252 84695 : && (INTVAL (XEXP (src, 1))
1253 641 : == INTVAL (XEXP (SET_SRC (prev_set), 1))))
1254 : {
1255 15 : unsigned HOST_WIDE_INT src_mask = GET_MODE_BITSIZE (GET_MODE (src)).to_constant ();
1256 15 : src_mask -= INTVAL (XEXP (src, 1));
1257 15 : src_mask = (HOST_WIDE_INT_1U << src_mask) - 1;
1258 :
1259 : /* DST_MASK has been adjusted for INSN. We need its original value. */
1260 15 : unsigned HOST_WIDE_INT tmp_mask = 0;
1261 75 : for (int i = 0; i < 4; i++)
1262 60 : if (bitmap_bit_p (live_tmp, 4 * rn + i))
1263 15 : tmp_mask |= mask_array[i];
1264 15 : tmp_mask >>= bit;
1265 :
1266 15 : if (modify && !skipped_dest && (tmp_mask & ~src_mask) == 0)
1267 : {
1268 0 : ext_dce_try_optimize_rshift (insn, x, XEXP (SET_SRC (prev_set), 0), prev_insn);
1269 :
1270 : /* These may not strictly be necessary, but we might as well try and be
1271 : as accurate as possible. The RHS is now a simple REG. */
1272 0 : dst_mask = src_mask;
1273 0 : src = XEXP (SET_SRC (prev_set), 0);
1274 0 : code = GET_CODE (src);
1275 : }
1276 : }
1277 : }
1278 :
1279 : /* Optimization is done at this point. We just want to make
1280 : sure everything that should get marked as live is marked
1281 : from here onward. */
1282 :
1283 : /* We will handle the other operand of a binary operator
1284 : at the bottom of the loop by resetting Y. */
1285 73127003 : if (BINARY_P (src))
1286 22820693 : y = XEXP (src, 0);
1287 : else
1288 : y = src;
1289 :
1290 : /* We're inside a SET and want to process the source operands
1291 : making things live. Breaking from this loop will cause
1292 : the iterator to work on sub-rtxs, so it is safe to break
1293 : if we see something we don't know how to handle.
1294 :
1295 : This code is just hokey as it really just handles trivial
1296 : unary and binary cases. Otherwise the loop exits and we
1297 : continue iterating on sub-rtxs, but outside the set context. */
1298 73127003 : unsigned HOST_WIDE_INT save_mask = dst_mask;
1299 117750339 : for (;;)
1300 : {
1301 : /* In general we want to restore DST_MASK before each loop
1302 : iteration. The exception is when the opcode implies that
1303 : the other operand is fully live. That's handled by
1304 : changing SAVE_MASK below. */
1305 95438671 : dst_mask = save_mask;
1306 : /* Strip an outer paradoxical subreg. The bits outside
1307 : the inner mode are don't cares. So we can just strip
1308 : and process the inner object. */
1309 95438671 : if (paradoxical_subreg_p (y))
1310 : y = XEXP (y, 0);
1311 95338723 : else if (SUBREG_P (y) && subreg_lsb (y).is_constant (&bit))
1312 : {
1313 : /* If !TRULY_NOOP_TRUNCATION_MODES_P, the mode
1314 : change performed by Y would normally need to be a
1315 : TRUNCATE rather than a SUBREG. It is probably the
1316 : guarantee provided by SUBREG_PROMOTED_VAR_P that
1317 : allows the SUBREG in Y as an exception. We must
1318 : therefore preserve that guarantee and treat the
1319 : upper bits of the inner register as live
1320 : regardless of the outer code. See PR 120050. */
1321 1981969 : if (!REG_P (SUBREG_REG (y))
1322 1981969 : || (SUBREG_PROMOTED_VAR_P (y)
1323 14138 : && (!TRULY_NOOP_TRUNCATION_MODES_P (
1324 : GET_MODE (y),
1325 : GET_MODE (SUBREG_REG (y))))))
1326 : break;
1327 :
1328 : /* If this is a wide object (more bits than we can fit
1329 : in a HOST_WIDE_INT), then just break from the SET
1330 : context. That will cause the iterator to walk down
1331 : into the subrtx and if we land on a REG we'll mark
1332 : the whole think live. */
1333 1980953 : if (bit >= HOST_BITS_PER_WIDE_INT)
1334 : break;
1335 :
1336 : /* The SUBREG's mode determines the live width. */
1337 1769712 : if (dst_mask)
1338 : {
1339 1769540 : dst_mask <<= bit;
1340 1769540 : if (!dst_mask)
1341 0 : dst_mask = -HOST_WIDE_INT_UC (0x100000000);
1342 : }
1343 1769712 : y = SUBREG_REG (y);
1344 : }
1345 :
1346 95226414 : if (REG_P (y))
1347 : {
1348 : /* We have found the use of a register. We need to mark
1349 : the appropriate chunks of the register live. The mode
1350 : of the REG is a starting point. We may refine that
1351 : based on what chunks in the output were live. */
1352 50905826 : rn = 4 * REGNO (y);
1353 50905826 : unsigned HOST_WIDE_INT tmp_mask = dst_mask;
1354 :
1355 : /* If the RTX code for the SET_SRC is not one we can
1356 : propagate destination liveness through, then just
1357 : set the mask to the mode's mask. */
1358 50905826 : if (!safe_for_live_propagation (code))
1359 34214 : tmp_mask = GET_MODE_MASK (GET_MODE (y));
1360 :
1361 50905826 : if (tmp_mask & 0xff)
1362 50437000 : bitmap_set_bit (livenow, rn);
1363 50905826 : if (tmp_mask & 0xff00)
1364 48571508 : bitmap_set_bit (livenow, rn + 1);
1365 50905826 : if (tmp_mask & HOST_WIDE_INT_UC (0xffff0000))
1366 48315824 : bitmap_set_bit (livenow, rn + 2);
1367 50905826 : if (tmp_mask & -HOST_WIDE_INT_UC (0x100000000))
1368 42146499 : bitmap_set_bit (livenow, rn + 3);
1369 : }
1370 44320588 : else if (!CONSTANT_P (y))
1371 : break;
1372 :
1373 : /* We might have (ashift (const_int 1) (reg...))
1374 : By setting dst_mask we can continue iterating on the
1375 : the next operand and it will be considered fully live.
1376 :
1377 : Note that since we restore DST_MASK from SAVE_MASK at the
1378 : top of the loop, we have to change SAVE_MASK to get the
1379 : semantics we want. */
1380 78385162 : if (binop_implies_op2_fully_live (GET_CODE (src)))
1381 2545975 : save_mask = -1;
1382 :
1383 : /* If this was anything but a binary operand, break the inner
1384 : loop. This is conservatively correct as it will cause the
1385 : iterator to look at the sub-rtxs outside the SET context. */
1386 78385162 : if (!BINARY_P (src))
1387 : break;
1388 :
1389 : /* We processed the first operand of a binary operator. Now
1390 : handle the second. */
1391 22311668 : y = XEXP (src, 1), src = pc_rtx;
1392 22311668 : }
1393 :
1394 : /* These are leaf nodes, no need to iterate down into them. */
1395 73127003 : if (REG_P (y) || CONSTANT_P (y))
1396 56073494 : iter.skip_subrtxes ();
1397 : }
1398 : }
1399 : /* If we are reading the low part of a SUBREG, then we can
1400 : refine liveness of the input register, otherwise let the
1401 : iterator continue into SUBREG_REG. */
1402 496011362 : else if (SUBREG_P (x)
1403 1446074 : && REG_P (SUBREG_REG (x))
1404 1444238 : && !paradoxical_subreg_p (x)
1405 1416184 : && subreg_lowpart_p (x)
1406 1125348 : && GET_MODE_BITSIZE (GET_MODE (x)).is_constant ()
1407 498262058 : && GET_MODE_BITSIZE (GET_MODE (x)).to_constant () <= 32)
1408 : {
1409 564994 : HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (x)).to_constant ();
1410 564994 : HOST_WIDE_INT rn = 4 * REGNO (SUBREG_REG (x));
1411 :
1412 : /* If this is a promoted subreg, then more of it may be live than
1413 : is otherwise obvious. */
1414 564994 : if (SUBREG_PROMOTED_VAR_P (x))
1415 4688 : size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))).to_constant ();
1416 :
1417 564994 : bitmap_set_bit (livenow, rn);
1418 564994 : if (size > 8)
1419 390360 : bitmap_set_bit (livenow, rn + 1);
1420 390360 : if (size > 16)
1421 350165 : bitmap_set_bit (livenow, rn + 2);
1422 350165 : if (size > 32)
1423 74 : bitmap_set_bit (livenow, rn + 3);
1424 564994 : iter.skip_subrtxes ();
1425 : }
1426 : /* If we have a register reference that is not otherwise handled,
1427 : just assume all the chunks are live. */
1428 495446368 : else if (REG_P (x))
1429 164264781 : bitmap_set_range (livenow, REGNO (x) * 4, group_limit (x));
1430 : }
1431 140964819 : }
1432 :
1433 : /* Process a single basic block BB with current liveness information
1434 : in LIVENOW, returning updated liveness information.
1435 :
1436 : If MODIFY is true, then this is the last pass and unnecessary
1437 : extensions should be eliminated when possible. If an extension
1438 : is removed, the source pseudo is marked in CHANGED_PSEUDOS. */
1439 :
1440 : static void
1441 23453200 : ext_dce_process_bb (basic_block bb)
1442 : {
1443 23453200 : rtx_insn *insn;
1444 :
1445 318727550 : FOR_BB_INSNS_REVERSE (bb, insn)
1446 : {
1447 295274350 : if (!NONDEBUG_INSN_P (insn))
1448 164082856 : continue;
1449 :
1450 : /* Live-out state of the destination of this insn. We can
1451 : use this to refine the live-in state of the sources of
1452 : this insn in many cases. */
1453 131191494 : bitmap live_tmp = BITMAP_ALLOC (NULL);
1454 :
1455 : /* First process any sets/clobbers in INSN. */
1456 131191494 : bool skipped_dest = ext_dce_process_sets (insn, PATTERN (insn), live_tmp);
1457 :
1458 : /* CALL_INSNs need processing their fusage data. */
1459 131191494 : if (CALL_P (insn))
1460 9773325 : skipped_dest |= ext_dce_process_sets (insn,
1461 : CALL_INSN_FUNCTION_USAGE (insn),
1462 : live_tmp);
1463 :
1464 : /* And now uses, optimizing away SIGN/ZERO extensions as we go. */
1465 131191494 : ext_dce_process_uses (insn, PATTERN (insn), live_tmp, skipped_dest);
1466 :
1467 : /* A nonlocal goto implicitly uses the frame pointer. */
1468 131191494 : if (JUMP_P (insn) && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1469 : {
1470 1130 : bitmap_set_range (livenow, FRAME_POINTER_REGNUM * 4, 4);
1471 1130 : if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
1472 1130 : bitmap_set_range (livenow, HARD_FRAME_POINTER_REGNUM * 4, 4);
1473 : }
1474 :
1475 : /* And process fusage data for the use as well. */
1476 131191494 : if (CALL_P (insn))
1477 : {
1478 9773325 : if (!FAKE_CALL_P (insn))
1479 9773265 : bitmap_set_range (livenow, STACK_POINTER_REGNUM * 4, 4);
1480 :
1481 : /* If this is not a call to a const function, then assume it
1482 : can read any global register. */
1483 9773325 : if (!RTL_CONST_CALL_P (insn))
1484 879908805 : for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1485 870447420 : if (global_regs[i])
1486 230 : bitmap_set_range (livenow, i * 4, 4);
1487 :
1488 9773325 : ext_dce_process_uses (insn, CALL_INSN_FUNCTION_USAGE (insn), live_tmp, false);
1489 : }
1490 :
1491 131191494 : BITMAP_FREE (live_tmp);
1492 : }
1493 :
1494 23453200 : if (modify)
1495 10027489 : ext_dce_promote_chained_candidates ();
1496 23453200 : }
1497 :
1498 : /* SUBREG_PROMOTED_VAR_P is set by the gimple->rtl optimizers and
1499 : is usually helpful. However, in some cases setting the value when
1500 : it not strictly needed can cause this pass to miss optimizations.
1501 :
1502 : Specifically consider (set (mem) (subreg (reg))). If set in that
1503 : case it will cause more bit groups to be live for REG than would
1504 : be strictly necessary which in turn can inhibit extension removal.
1505 :
1506 : So do a pass over the IL wiping the SUBREG_PROMOTED_VAR_P when it
1507 : is obviously not needed. */
1508 :
1509 : static void
1510 981310 : maybe_clear_subreg_promoted_p (void)
1511 : {
1512 126568188 : for (rtx_insn *insn = get_insns(); insn; insn = NEXT_INSN (insn))
1513 : {
1514 125586878 : if (!NONDEBUG_INSN_P (insn))
1515 69369421 : continue;
1516 :
1517 56217457 : rtx set = single_set (insn);
1518 56217457 : if (!set)
1519 3760330 : continue;
1520 :
1521 : /* There may be other cases where we should clear, but for
1522 : now, this is the only known case where it causes problems. */
1523 52457127 : if (MEM_P (SET_DEST (set)) && SUBREG_P (SET_SRC (set))
1524 86046 : && GET_MODE (SET_DEST (set)) <= GET_MODE (SUBREG_REG (SET_SRC (set))))
1525 75693 : SUBREG_PROMOTED_VAR_P (SET_SRC (set)) = 0;
1526 : }
1527 981310 : }
1528 :
1529 : /* Walk the IL and build the transitive closure of all the REGs tied
1530 : together by copies where either the source or destination is
1531 : marked in CHANGED_PSEUDOS. */
1532 :
1533 : static void
1534 981310 : expand_changed_pseudos (void)
1535 : {
1536 : /* Build a vector of registers related by a copy. This is meant to
1537 : speed up the next step by avoiding full IL walks. */
1538 981310 : struct copy_pair { rtx first; rtx second; };
1539 981310 : auto_vec<copy_pair> pairs;
1540 126568188 : for (rtx_insn *insn = get_insns(); insn; insn = NEXT_INSN (insn))
1541 : {
1542 125586878 : if (!NONDEBUG_INSN_P (insn))
1543 69369421 : continue;
1544 :
1545 56217457 : rtx pat = PATTERN (insn);
1546 :
1547 : /* Simple copies to a REG from another REG or SUBREG of a REG. */
1548 56217457 : if (GET_CODE (pat) == SET
1549 44370579 : && REG_P (SET_DEST (pat))
1550 31669372 : && (REG_P (SET_SRC (pat))
1551 22871817 : || (SUBREG_P (SET_SRC (pat))
1552 398574 : && REG_P (SUBREG_REG (SET_SRC (pat))))))
1553 : {
1554 398136 : rtx src = (REG_P (SET_SRC (pat))
1555 9195691 : ? SET_SRC (pat)
1556 : : SUBREG_REG (SET_SRC (pat)));
1557 9195691 : pairs.safe_push ({ SET_DEST (pat), src });
1558 : }
1559 :
1560 : /* Simple copies to a REG from another REG or SUBREG of a REG
1561 : held inside a PARALLEL. */
1562 56217457 : if (GET_CODE (pat) == PARALLEL)
1563 : {
1564 25492322 : for (int i = XVECLEN (pat, 0) - 1; i >= 0; i--)
1565 : {
1566 17118532 : rtx elem = XVECEXP (pat, 0, i);
1567 :
1568 17118532 : if (GET_CODE (elem) == SET
1569 8618944 : && REG_P (SET_DEST (elem))
1570 8458113 : && (REG_P (SET_SRC (elem))
1571 8458113 : || (SUBREG_P (SET_SRC (elem))
1572 0 : && REG_P (SUBREG_REG (SET_SRC (elem))))))
1573 : {
1574 0 : rtx src = (REG_P (SET_SRC (elem))
1575 0 : ? SET_SRC (elem)
1576 : : SUBREG_REG (SET_SRC (elem)));
1577 0 : pairs.safe_push ({ SET_DEST (elem), src });
1578 : }
1579 : }
1580 8373790 : continue;
1581 8373790 : }
1582 : }
1583 :
1584 : /* Now we have a vector with copy pairs. Iterate over that list
1585 : updating CHANGED_PSEUDOS as we go. Eliminate copies from the
1586 : list as we go as they don't need further processing. */
1587 : bool changed = true;
1588 1962723 : while (changed)
1589 : {
1590 : changed = false;
1591 : unsigned int i;
1592 : copy_pair *p;
1593 11159949 : FOR_EACH_VEC_ELT (pairs, i, p)
1594 : {
1595 9197226 : if (bitmap_bit_p (changed_pseudos, REGNO (p->second))
1596 9197226 : && bitmap_set_bit (changed_pseudos, REGNO (p->first)))
1597 : {
1598 114 : pairs.unordered_remove (i);
1599 114 : changed = true;
1600 : }
1601 : }
1602 : }
1603 981310 : }
1604 :
1605 : /* We optimize away sign/zero extensions in this pass and replace
1606 : them with SUBREGs indicating certain bits are don't cares.
1607 :
1608 : This changes the SUBREG_PROMOTED_VAR_P state of the object.
1609 : It is fairly painful to fix this on the fly, so we have
1610 : recorded which pseudos are affected and we look for SUBREGs
1611 : of those pseudos and fix them up. */
1612 :
1613 : static void
1614 981310 : reset_subreg_promoted_p (void)
1615 : {
1616 : /* This pass eliminates zero/sign extensions on pseudo regs found
1617 : in CHANGED_PSEUDOS. Elimination of those extensions changes if
1618 : the pseudos are known to hold values extended to wider modes
1619 : via SUBREG_PROMOTED_VAR. So we wipe the SUBREG_PROMOTED_VAR
1620 : state on all affected pseudos.
1621 :
1622 : But that is insufficient. We might have a copy from one REG
1623 : to another (possibly with the source register wrapped with a
1624 : SUBREG). We need to wipe SUBREG_PROMOTED_VAR on the transitive
1625 : closure of the original CHANGED_PSEUDOS and registers they're
1626 : connected to via copies. So expand the set. */
1627 981310 : expand_changed_pseudos ();
1628 :
1629 : /* If we removed an extension, that changed the promoted state
1630 : of the destination of that extension. Thus we need to go
1631 : find any SUBREGs that reference that pseudo and adjust their
1632 : SUBREG_PROMOTED_P state. */
1633 126568188 : for (rtx_insn *insn = get_insns(); insn; insn = NEXT_INSN (insn))
1634 : {
1635 125586878 : if (!NONDEBUG_INSN_P (insn))
1636 69369421 : continue;
1637 :
1638 56217457 : rtx pat = PATTERN (insn);
1639 56217457 : subrtx_var_iterator::array_type array;
1640 358510925 : FOR_EACH_SUBRTX_VAR (iter, array, pat, NONCONST)
1641 : {
1642 302293468 : rtx sub = *iter;
1643 :
1644 : /* We only care about SUBREGs. */
1645 302293468 : if (GET_CODE (sub) != SUBREG)
1646 300656844 : continue;
1647 :
1648 1636624 : const_rtx x = SUBREG_REG (sub);
1649 :
1650 : /* We only care if the inner object is a REG. */
1651 1636624 : if (!REG_P (x))
1652 772 : continue;
1653 :
1654 : /* And only if the SUBREG is a promoted var. */
1655 1635852 : if (!SUBREG_PROMOTED_VAR_P (sub))
1656 1630103 : continue;
1657 :
1658 5749 : if (bitmap_bit_p (changed_pseudos, REGNO (x)))
1659 0 : SUBREG_PROMOTED_VAR_P (sub) = 0;
1660 : }
1661 56217457 : }
1662 981310 : }
1663 :
1664 : /* Initialization of the ext-dce pass. Primarily this means
1665 : setting up the various bitmaps we utilize. */
1666 :
1667 : static void
1668 981310 : ext_dce_init (void)
1669 : {
1670 981310 : livein.create (last_basic_block_for_fn (cfun));
1671 981310 : livein.quick_grow_cleared (last_basic_block_for_fn (cfun));
1672 13961543 : for (int i = 0; i < last_basic_block_for_fn (cfun); i++)
1673 11998923 : bitmap_initialize (&livein[i], &bitmap_default_obstack);
1674 :
1675 981310 : auto_bitmap refs (&bitmap_default_obstack);
1676 981310 : df_get_exit_block_use_set (refs);
1677 :
1678 981310 : unsigned i;
1679 981310 : bitmap_iterator bi;
1680 4513837 : EXECUTE_IF_SET_IN_BITMAP (refs, 0, i, bi)
1681 3532527 : make_reg_live (&livein[EXIT_BLOCK], i);
1682 :
1683 981310 : livenow = BITMAP_ALLOC (NULL);
1684 981310 : all_blocks = BITMAP_ALLOC (NULL);
1685 981310 : changed_pseudos = BITMAP_ALLOC (NULL);
1686 981310 : promotable_dests = BITMAP_ALLOC (NULL);
1687 981310 : consumed_by_candidate = BITMAP_ALLOC (NULL);
1688 :
1689 12980233 : for (int i = 0; i < last_basic_block_for_fn (cfun); i++)
1690 11998923 : if (i != ENTRY_BLOCK && i != EXIT_BLOCK)
1691 10036303 : bitmap_set_bit (all_blocks, i);
1692 :
1693 981310 : modify = false;
1694 981310 : }
1695 :
1696 : /* Finalization of the ext-dce pass. Primarily this means
1697 : releasing up the various bitmaps we utilize. */
1698 :
1699 : static void
1700 981310 : ext_dce_finish (void)
1701 : {
1702 12980233 : for (unsigned i = 0; i < livein.length (); i++)
1703 11998923 : bitmap_clear (&livein[i]);
1704 981310 : livein.release ();
1705 :
1706 981310 : BITMAP_FREE (livenow);
1707 981310 : BITMAP_FREE (changed_pseudos);
1708 981310 : BITMAP_FREE (all_blocks);
1709 981310 : BITMAP_FREE (promotable_dests);
1710 981310 : BITMAP_FREE (consumed_by_candidate);
1711 981310 : promotion_candidates.release ();
1712 981310 : promotion_copies.release ();
1713 981310 : }
1714 :
1715 : /* Process block number BB_INDEX as part of the backward
1716 : simple dataflow analysis. Return TRUE if something in
1717 : this block changed or FALSE otherwise. */
1718 :
1719 : static bool
1720 27378440 : ext_dce_rd_transfer_n (int bb_index)
1721 : {
1722 : /* The ENTRY/EXIT blocks never change. */
1723 27378440 : if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK)
1724 : return false;
1725 :
1726 23453200 : basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
1727 :
1728 : /* Make everything live that's live in the successors. */
1729 23453200 : bitmap_clear (livenow);
1730 23453200 : edge_iterator ei;
1731 23453200 : edge e;
1732 :
1733 58957286 : FOR_EACH_EDGE (e, ei, bb->succs)
1734 35504086 : bitmap_ior_into (livenow, &livein[e->dest->index]);
1735 :
1736 23453200 : ext_dce_process_bb (bb);
1737 :
1738 : /* We only allow widening the set of objects live at the start
1739 : of a block. Otherwise we run the risk of not converging. */
1740 23453200 : return bitmap_ior_into (&livein[bb_index], livenow);
1741 : }
1742 :
1743 : /* Dummy function for the df_simple_dataflow API. */
1744 34136899 : static bool ext_dce_rd_confluence_n (edge) { return true; }
1745 :
1746 : /* Use lifetime analysis to identify extensions that set bits that
1747 : are never read. Turn such extensions into SUBREGs instead which
1748 : can often be propagated away. */
1749 :
1750 : void
1751 981310 : ext_dce_execute (void)
1752 : {
1753 : /* Limit the amount of memory we use for livein, with 4 bits per
1754 : reg per basic-block including overhead that maps to one byte
1755 : per reg per basic-block. */
1756 981310 : uint64_t memory_request
1757 981310 : = (uint64_t)n_basic_blocks_for_fn (cfun) * max_reg_num ();
1758 981310 : if (memory_request / 1024 > (uint64_t)param_max_gcse_memory)
1759 : {
1760 0 : warning (OPT_Wdisabled_optimization,
1761 : "ext-dce disabled: %d basic blocks and %d registers; "
1762 : "increase %<--param max-gcse-memory%> above %wu",
1763 0 : n_basic_blocks_for_fn (cfun), max_reg_num (),
1764 : memory_request / 1024);
1765 0 : return;
1766 : }
1767 :
1768 : /* Some settings of SUBREG_PROMOTED_VAR_P are actively harmful
1769 : to this pass. Clear it for those cases. */
1770 981310 : maybe_clear_subreg_promoted_p ();
1771 981310 : df_analyze ();
1772 981310 : ext_dce_init ();
1773 :
1774 3925240 : do
1775 : {
1776 1962620 : df_simple_dataflow (DF_BACKWARD, NULL, NULL,
1777 : ext_dce_rd_confluence_n, ext_dce_rd_transfer_n,
1778 : all_blocks, df_get_postorder (DF_BACKWARD),
1779 : df_get_n_blocks (DF_BACKWARD));
1780 1962620 : modify = !modify;
1781 : }
1782 : while (modify);
1783 :
1784 981310 : reset_subreg_promoted_p ();
1785 :
1786 981310 : ext_dce_finish ();
1787 : }
1788 :
1789 :
1790 : namespace {
1791 :
1792 : const pass_data pass_data_ext_dce =
1793 : {
1794 : RTL_PASS, /* type */
1795 : "ext_dce", /* name */
1796 : OPTGROUP_NONE, /* optinfo_flags */
1797 : TV_EXT_DCE, /* tv_id */
1798 : PROP_cfglayout, /* properties_required */
1799 : 0, /* properties_provided */
1800 : 0, /* properties_destroyed */
1801 : 0, /* todo_flags_start */
1802 : TODO_df_finish, /* todo_flags_finish */
1803 : };
1804 :
1805 : class pass_ext_dce : public rtl_opt_pass
1806 : {
1807 : public:
1808 294196 : pass_ext_dce (gcc::context *ctxt)
1809 588392 : : rtl_opt_pass (pass_data_ext_dce, ctxt)
1810 : {}
1811 :
1812 : /* opt_pass methods: */
1813 1515129 : virtual bool gate (function *) { return flag_ext_dce && optimize > 0; }
1814 981310 : virtual unsigned int execute (function *)
1815 : {
1816 981310 : ext_dce_execute ();
1817 981310 : return 0;
1818 : }
1819 :
1820 : }; // class pass_combine
1821 :
1822 : } // anon namespace
1823 :
1824 : rtl_opt_pass *
1825 294196 : make_pass_ext_dce (gcc::context *ctxt)
1826 : {
1827 294196 : return new pass_ext_dce (ctxt);
1828 : }
|