Mercurial > hg > CbC > CbC_gcc
comparison gcc/compare-elim.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* Post-reload compare elimination. | 1 /* Post-reload compare elimination. |
2 Copyright (C) 2010-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2010-2018 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 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 | 7 the terms of the GNU General Public License as published by the Free |
94 /* The comparison instruction. */ | 94 /* The comparison instruction. */ |
95 rtx_insn *insn; | 95 rtx_insn *insn; |
96 | 96 |
97 /* The insn prior to the comparison insn that clobbers the flags. */ | 97 /* The insn prior to the comparison insn that clobbers the flags. */ |
98 rtx_insn *prev_clobber; | 98 rtx_insn *prev_clobber; |
99 | |
100 /* The insn prior to the comparison insn that sets in_a REG. */ | |
101 rtx_insn *in_a_setter; | |
99 | 102 |
100 /* The two values being compared. These will be either REGs or | 103 /* The two values being compared. These will be either REGs or |
101 constants. */ | 104 constants. */ |
102 rtx in_a, in_b; | 105 rtx in_a, in_b; |
103 | 106 |
307 in BB->AUX. Called via dom_walker.walk (). */ | 310 in BB->AUX. Called via dom_walker.walk (). */ |
308 | 311 |
309 edge | 312 edge |
310 find_comparison_dom_walker::before_dom_children (basic_block bb) | 313 find_comparison_dom_walker::before_dom_children (basic_block bb) |
311 { | 314 { |
312 struct comparison *last_cmp; | 315 rtx_insn *insn, *next; |
313 rtx_insn *insn, *next, *last_clobber; | |
314 bool last_cmp_valid; | |
315 bool need_purge = false; | 316 bool need_purge = false; |
316 bitmap killed; | 317 rtx_insn *last_setter[FIRST_PSEUDO_REGISTER]; |
317 | |
318 killed = BITMAP_ALLOC (NULL); | |
319 | 318 |
320 /* The last comparison that was made. Will be reset to NULL | 319 /* The last comparison that was made. Will be reset to NULL |
321 once the flags are clobbered. */ | 320 once the flags are clobbered. */ |
322 last_cmp = NULL; | 321 struct comparison *last_cmp = NULL; |
323 | 322 |
324 /* True iff the last comparison has not been clobbered, nor | 323 /* True iff the last comparison has not been clobbered, nor |
325 have its inputs. Used to eliminate duplicate compares. */ | 324 have its inputs. Used to eliminate duplicate compares. */ |
326 last_cmp_valid = false; | 325 bool last_cmp_valid = false; |
327 | 326 |
328 /* The last insn that clobbered the flags, if that insn is of | 327 /* The last insn that clobbered the flags, if that insn is of |
329 a form that may be valid for eliminating a following compare. | 328 a form that may be valid for eliminating a following compare. |
330 To be reset to NULL once the flags are set otherwise. */ | 329 To be reset to NULL once the flags are set otherwise. */ |
331 last_clobber = NULL; | 330 rtx_insn *last_clobber = NULL; |
332 | 331 |
333 /* Propagate the last live comparison throughout the extended basic block. */ | 332 /* Propagate the last live comparison throughout the extended basic block. */ |
334 if (single_pred_p (bb)) | 333 if (single_pred_p (bb)) |
335 { | 334 { |
336 last_cmp = (struct comparison *) single_pred (bb)->aux; | 335 last_cmp = (struct comparison *) single_pred (bb)->aux; |
337 if (last_cmp) | 336 if (last_cmp) |
338 last_cmp_valid = last_cmp->inputs_valid; | 337 last_cmp_valid = last_cmp->inputs_valid; |
339 } | 338 } |
340 | 339 |
340 memset (last_setter, 0, sizeof (last_setter)); | |
341 for (insn = BB_HEAD (bb); insn; insn = next) | 341 for (insn = BB_HEAD (bb); insn; insn = next) |
342 { | 342 { |
343 rtx src; | 343 rtx src; |
344 | 344 |
345 next = (insn == BB_END (bb) ? NULL : NEXT_INSN (insn)); | 345 next = (insn == BB_END (bb) ? NULL : NEXT_INSN (insn)); |
346 if (!NONDEBUG_INSN_P (insn)) | 346 if (!NONDEBUG_INSN_P (insn)) |
347 continue; | 347 continue; |
348 | |
349 /* Compute the set of registers modified by this instruction. */ | |
350 bitmap_clear (killed); | |
351 df_simulate_find_defs (insn, killed); | |
352 | 348 |
353 src = conforming_compare (insn); | 349 src = conforming_compare (insn); |
354 if (src) | 350 if (src) |
355 { | 351 { |
356 rtx eh_note = NULL; | 352 rtx eh_note = NULL; |
371 last_cmp->prev_clobber = last_clobber; | 367 last_cmp->prev_clobber = last_clobber; |
372 last_cmp->in_a = XEXP (src, 0); | 368 last_cmp->in_a = XEXP (src, 0); |
373 last_cmp->in_b = XEXP (src, 1); | 369 last_cmp->in_b = XEXP (src, 1); |
374 last_cmp->eh_note = eh_note; | 370 last_cmp->eh_note = eh_note; |
375 last_cmp->orig_mode = GET_MODE (src); | 371 last_cmp->orig_mode = GET_MODE (src); |
372 if (last_cmp->in_b == const0_rtx | |
373 && last_setter[REGNO (last_cmp->in_a)]) | |
374 { | |
375 rtx set = single_set (last_setter[REGNO (last_cmp->in_a)]); | |
376 if (set && rtx_equal_p (SET_DEST (set), last_cmp->in_a)) | |
377 last_cmp->in_a_setter = last_setter[REGNO (last_cmp->in_a)]; | |
378 } | |
376 all_compares.safe_push (last_cmp); | 379 all_compares.safe_push (last_cmp); |
377 | 380 |
378 /* It's unusual, but be prepared for comparison patterns that | 381 /* It's unusual, but be prepared for comparison patterns that |
379 also clobber an input, or perhaps a scratch. */ | 382 also clobber an input, or perhaps a scratch. */ |
380 last_clobber = NULL; | 383 last_clobber = NULL; |
386 /* Notice if this instruction uses the flags register. */ | 389 /* Notice if this instruction uses the flags register. */ |
387 if (last_cmp) | 390 if (last_cmp) |
388 find_flags_uses_in_insn (last_cmp, insn); | 391 find_flags_uses_in_insn (last_cmp, insn); |
389 | 392 |
390 /* Notice if this instruction kills the flags register. */ | 393 /* Notice if this instruction kills the flags register. */ |
391 if (bitmap_bit_p (killed, targetm.flags_regnum)) | 394 df_ref def; |
392 { | 395 FOR_EACH_INSN_DEF (def, insn) |
393 /* See if this insn could be the "clobber" that eliminates | 396 if (DF_REF_REGNO (def) == targetm.flags_regnum) |
394 a future comparison. */ | 397 { |
395 last_clobber = (arithmetic_flags_clobber_p (insn) ? insn : NULL); | 398 /* See if this insn could be the "clobber" that eliminates |
396 | 399 a future comparison. */ |
397 /* In either case, the previous compare is no longer valid. */ | 400 last_clobber = (arithmetic_flags_clobber_p (insn) |
398 last_cmp = NULL; | 401 ? insn : NULL); |
399 last_cmp_valid = false; | 402 |
400 } | 403 /* In either case, the previous compare is no longer valid. */ |
404 last_cmp = NULL; | |
405 last_cmp_valid = false; | |
406 break; | |
407 } | |
401 } | 408 } |
402 | 409 |
403 /* Notice if any of the inputs to the comparison have changed. */ | 410 /* Notice if any of the inputs to the comparison have changed |
404 if (last_cmp_valid | 411 and remember last insn that sets each register. */ |
405 && (bitmap_bit_p (killed, REGNO (last_cmp->in_a)) | 412 df_ref def; |
406 || (REG_P (last_cmp->in_b) | 413 FOR_EACH_INSN_DEF (def, insn) |
407 && bitmap_bit_p (killed, REGNO (last_cmp->in_b))))) | 414 { |
408 last_cmp_valid = false; | 415 if (last_cmp_valid |
409 } | 416 && (DF_REF_REGNO (def) == REGNO (last_cmp->in_a) |
410 | 417 || (REG_P (last_cmp->in_b) |
411 BITMAP_FREE (killed); | 418 && DF_REF_REGNO (def) == REGNO (last_cmp->in_b)))) |
419 last_cmp_valid = false; | |
420 last_setter[DF_REF_REGNO (def)] = insn; | |
421 } | |
422 } | |
412 | 423 |
413 /* Remember the live comparison for subsequent members of | 424 /* Remember the live comparison for subsequent members of |
414 the extended basic block. */ | 425 the extended basic block. */ |
415 if (last_cmp) | 426 if (last_cmp) |
416 { | 427 { |
623 if so. Otherwise return NULL. */ | 634 if so. Otherwise return NULL. */ |
624 | 635 |
625 static rtx | 636 static rtx |
626 try_validate_parallel (rtx set_a, rtx set_b) | 637 try_validate_parallel (rtx set_a, rtx set_b) |
627 { | 638 { |
628 rtx par | 639 rtx par = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set_a, set_b)); |
629 = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set_a, set_b)); | 640 rtx_insn *insn = make_insn_raw (par); |
630 | 641 |
631 rtx_insn *insn; | 642 if (insn_invalid_p (insn, false)) |
632 insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, par, 0, -1, 0); | 643 { |
633 | 644 crtl->emit.x_cur_insn_uid--; |
634 return recog_memoized (insn) > 0 ? par : NULL_RTX; | 645 return NULL_RTX; |
646 } | |
647 | |
648 SET_PREV_INSN (insn) = NULL_RTX; | |
649 SET_NEXT_INSN (insn) = NULL_RTX; | |
650 INSN_LOCATION (insn) = 0; | |
651 return insn; | |
635 } | 652 } |
636 | 653 |
637 /* For a comparison instruction described by CMP check if it compares a | 654 /* For a comparison instruction described by CMP check if it compares a |
638 register with zero i.e. it is of the form CC := CMP R1, 0. | 655 register with zero i.e. it is of the form CC := CMP R1, 0. |
639 If it is, find the instruction defining R1 (say I1) and try to create a | 656 If it is, find the instruction defining R1 (say I1) and try to create a |
641 arithmetic instruction. Example: | 658 arithmetic instruction. Example: |
642 I1: R1 := R2 + R3 | 659 I1: R1 := R2 + R3 |
643 <instructions that don't read the condition register> | 660 <instructions that don't read the condition register> |
644 I2: CC := CMP R1 0 | 661 I2: CC := CMP R1 0 |
645 I2 can be merged with I1 into: | 662 I2 can be merged with I1 into: |
646 I1: { R1 := R2 + R3 ; CC := CMP (R2 + R3) 0 } | 663 I1: { CC := CMP (R2 + R3) 0 ; R1 := R2 + R3 } |
647 This catches cases where R1 is used between I1 and I2 and therefore | 664 This catches cases where R1 is used between I1 and I2 and therefore |
648 combine and other RTL optimisations will not try to propagate it into | 665 combine and other RTL optimisations will not try to propagate it into |
649 I2. Return true if we succeeded in merging CMP. */ | 666 I2. Return true if we succeeded in merging CMP. */ |
650 | 667 |
651 static bool | 668 static bool |
652 try_merge_compare (struct comparison *cmp) | 669 try_merge_compare (struct comparison *cmp) |
653 { | 670 { |
654 rtx_insn *cmp_insn = cmp->insn; | 671 rtx_insn *cmp_insn = cmp->insn; |
655 | 672 |
656 if (!REG_P (cmp->in_a) || cmp->in_b != const0_rtx) | 673 if (cmp->in_b != const0_rtx || cmp->in_a_setter == NULL) |
657 return false; | 674 return false; |
658 rtx in_a = cmp->in_a; | 675 rtx in_a = cmp->in_a; |
659 df_ref use; | 676 df_ref use; |
660 | 677 |
661 FOR_EACH_INSN_USE (use, cmp_insn) | 678 FOR_EACH_INSN_USE (use, cmp_insn) |
662 if (DF_REF_REGNO (use) == REGNO (in_a)) | 679 if (DF_REF_REGNO (use) == REGNO (in_a)) |
663 break; | 680 break; |
664 if (!use) | 681 if (!use) |
665 return false; | 682 return false; |
666 | 683 |
667 /* Validate the data flow information before attempting to | 684 rtx_insn *def_insn = cmp->in_a_setter; |
668 find the instruction that defines in_a. */ | |
669 | |
670 struct df_link *ref_chain; | |
671 ref_chain = DF_REF_CHAIN (use); | |
672 if (!ref_chain || !ref_chain->ref | |
673 || !DF_REF_INSN_INFO (ref_chain->ref) || ref_chain->next != NULL) | |
674 return false; | |
675 | |
676 rtx_insn *def_insn = DF_REF_INSN (ref_chain->ref); | |
677 /* We found the insn that defines in_a. Only consider the cases where | |
678 it is in the same block as the comparison. */ | |
679 if (BLOCK_FOR_INSN (cmp_insn) != BLOCK_FOR_INSN (def_insn)) | |
680 return false; | |
681 | |
682 rtx set = single_set (def_insn); | 685 rtx set = single_set (def_insn); |
683 if (!set) | 686 if (!set) |
684 return false; | 687 return false; |
685 | 688 |
686 if (!can_merge_compare_into_arith (cmp_insn, def_insn)) | 689 if (!can_merge_compare_into_arith (cmp_insn, def_insn)) |
687 return false; | 690 return false; |
688 | 691 |
689 rtx src = SET_SRC (set); | 692 rtx src = SET_SRC (set); |
693 | |
694 /* If the source uses addressing modes with side effects, we can't | |
695 do the merge because we'd end up with a PARALLEL that has two | |
696 instances of that side effect in it. */ | |
697 if (side_effects_p (src)) | |
698 return false; | |
699 | |
690 rtx flags = maybe_select_cc_mode (cmp, src, CONST0_RTX (GET_MODE (src))); | 700 rtx flags = maybe_select_cc_mode (cmp, src, CONST0_RTX (GET_MODE (src))); |
691 if (!flags) | 701 if (!flags) |
692 { | 702 { |
693 /* We may already have a change group going through maybe_select_cc_mode. | 703 /* We may already have a change group going through maybe_select_cc_mode. |
694 Discard it properly. */ | 704 Discard it properly. */ |
804 cmp_src = in_a; | 814 cmp_src = in_a; |
805 | 815 |
806 else | 816 else |
807 return false; | 817 return false; |
808 | 818 |
819 /* If the source uses addressing modes with side effects, we can't | |
820 do the merge because we'd end up with a PARALLEL that has two | |
821 instances of that side effect in it. */ | |
822 if (side_effects_p (cmp_src)) | |
823 return false; | |
824 | |
809 /* Determine if we ought to use a different CC_MODE here. */ | 825 /* Determine if we ought to use a different CC_MODE here. */ |
810 flags = maybe_select_cc_mode (cmp, cmp_src, in_b); | 826 flags = maybe_select_cc_mode (cmp, cmp_src, in_b); |
811 if (flags == NULL) | 827 if (flags == NULL) |
812 flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum); | 828 flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum); |
813 | 829 |
853 /* Main entry point to the pass. */ | 869 /* Main entry point to the pass. */ |
854 | 870 |
855 static unsigned int | 871 static unsigned int |
856 execute_compare_elim_after_reload (void) | 872 execute_compare_elim_after_reload (void) |
857 { | 873 { |
858 df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN); | |
859 df_analyze (); | 874 df_analyze (); |
860 | 875 |
861 gcc_checking_assert (!all_compares.exists ()); | 876 gcc_checking_assert (!all_compares.exists ()); |
862 | 877 |
863 /* Locate all comparisons and their uses, and eliminate duplicates. */ | 878 /* Locate all comparisons and their uses, and eliminate duplicates. */ |