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