Mercurial > hg > CbC > CbC_gcc
comparison gcc/compare-elim.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
1 /* Post-reload compare elimination. | 1 /* Post-reload compare elimination. |
2 Copyright (C) 2010-2018 Free Software Foundation, Inc. | 2 Copyright (C) 2010-2020 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 |
121 the flags register is used in some unusual context. */ | 121 the flags register is used in some unusual context. */ |
122 bool missing_uses; | 122 bool missing_uses; |
123 | 123 |
124 /* True if its inputs are still valid at the end of the block. */ | 124 /* True if its inputs are still valid at the end of the block. */ |
125 bool inputs_valid; | 125 bool inputs_valid; |
126 | |
127 /* Whether IN_A is wrapped in a NOT before being compared. */ | |
128 bool not_in_a; | |
126 }; | 129 }; |
127 | 130 |
128 static vec<comparison *> all_compares; | 131 static vec<comparison *> all_compares; |
129 | 132 |
133 /* Return whether X is a NOT unary expression. */ | |
134 | |
135 static bool | |
136 is_not (rtx x) | |
137 { | |
138 return GET_CODE (x) == NOT; | |
139 } | |
140 | |
141 /* Strip a NOT unary expression around X, if any. */ | |
142 | |
143 static rtx | |
144 strip_not (rtx x) | |
145 { | |
146 if (is_not (x)) | |
147 return XEXP (x, 0); | |
148 | |
149 return x; | |
150 } | |
151 | |
130 /* Look for a "conforming" comparison, as defined above. If valid, return | 152 /* Look for a "conforming" comparison, as defined above. If valid, return |
131 the rtx for the COMPARE itself. */ | 153 the rtx for the COMPARE itself. */ |
132 | 154 |
133 static rtx | 155 static rtx |
134 conforming_compare (rtx_insn *insn) | 156 conforming_compare (rtx_insn *insn) |
145 | 167 |
146 dest = SET_DEST (set); | 168 dest = SET_DEST (set); |
147 if (!REG_P (dest) || REGNO (dest) != targetm.flags_regnum) | 169 if (!REG_P (dest) || REGNO (dest) != targetm.flags_regnum) |
148 return NULL; | 170 return NULL; |
149 | 171 |
150 if (!REG_P (XEXP (src, 0))) | 172 if (!REG_P (strip_not (XEXP (src, 0)))) |
151 return NULL; | 173 return NULL; |
152 | 174 |
153 if (CONSTANT_P (XEXP (src, 1)) || REG_P (XEXP (src, 1))) | 175 if (CONSTANT_P (XEXP (src, 1)) || REG_P (XEXP (src, 1))) |
154 return src; | 176 return src; |
155 | 177 |
276 if (cfun->can_throw_non_call_exceptions | 298 if (cfun->can_throw_non_call_exceptions |
277 && !rtx_equal_p (eh_note, cmp->eh_note)) | 299 && !rtx_equal_p (eh_note, cmp->eh_note)) |
278 return false; | 300 return false; |
279 | 301 |
280 /* Make sure the compare is redundant with the previous. */ | 302 /* Make sure the compare is redundant with the previous. */ |
281 if (!rtx_equal_p (XEXP (compare, 0), cmp->in_a) | 303 if (!rtx_equal_p (strip_not (XEXP (compare, 0)), cmp->in_a) |
282 || !rtx_equal_p (XEXP (compare, 1), cmp->in_b)) | 304 || !rtx_equal_p (XEXP (compare, 1), cmp->in_b)) |
305 return false; | |
306 | |
307 if (is_not (XEXP (compare, 0)) != cmp->not_in_a) | |
283 return false; | 308 return false; |
284 | 309 |
285 /* New mode must be compatible with the previous compare mode. */ | 310 /* New mode must be compatible with the previous compare mode. */ |
286 machine_mode new_mode | 311 machine_mode new_mode |
287 = targetm.cc_modes_compatible (GET_MODE (compare), cmp->orig_mode); | 312 = targetm.cc_modes_compatible (GET_MODE (compare), cmp->orig_mode); |
363 } | 388 } |
364 | 389 |
365 last_cmp = XCNEW (struct comparison); | 390 last_cmp = XCNEW (struct comparison); |
366 last_cmp->insn = insn; | 391 last_cmp->insn = insn; |
367 last_cmp->prev_clobber = last_clobber; | 392 last_cmp->prev_clobber = last_clobber; |
368 last_cmp->in_a = XEXP (src, 0); | 393 last_cmp->in_a = strip_not (XEXP (src, 0)); |
369 last_cmp->in_b = XEXP (src, 1); | 394 last_cmp->in_b = XEXP (src, 1); |
395 last_cmp->not_in_a = is_not (XEXP (src, 0)); | |
370 last_cmp->eh_note = eh_note; | 396 last_cmp->eh_note = eh_note; |
371 last_cmp->orig_mode = GET_MODE (src); | 397 last_cmp->orig_mode = GET_MODE (src); |
372 if (last_cmp->in_b == const0_rtx | 398 if (last_cmp->in_b == const0_rtx |
373 && last_setter[REGNO (last_cmp->in_a)]) | 399 && last_setter[REGNO (last_cmp->in_a)]) |
374 { | 400 { |
732 successful, having made all rtl modifications necessary. */ | 758 successful, having made all rtl modifications necessary. */ |
733 | 759 |
734 static bool | 760 static bool |
735 try_eliminate_compare (struct comparison *cmp) | 761 try_eliminate_compare (struct comparison *cmp) |
736 { | 762 { |
737 rtx flags, in_a, in_b, cmp_src; | 763 rtx flags, in_a, in_b, cmp_a, cmp_b; |
738 | 764 |
739 if (try_merge_compare (cmp)) | 765 if (try_merge_compare (cmp)) |
740 return true; | 766 return true; |
741 | 767 |
742 /* We must have found an interesting "clobber" preceding the compare. */ | 768 /* We must have found an interesting "clobber" preceding the compare. */ |
784 recall that we've already validated the shape of PREV_CLOBBER. */ | 810 recall that we've already validated the shape of PREV_CLOBBER. */ |
785 rtx_insn *insn = cmp->prev_clobber; | 811 rtx_insn *insn = cmp->prev_clobber; |
786 | 812 |
787 rtx x = XVECEXP (PATTERN (insn), 0, 0); | 813 rtx x = XVECEXP (PATTERN (insn), 0, 0); |
788 if (rtx_equal_p (SET_DEST (x), in_a)) | 814 if (rtx_equal_p (SET_DEST (x), in_a)) |
789 cmp_src = SET_SRC (x); | 815 cmp_a = SET_SRC (x); |
790 | 816 |
791 /* Also check operations with implicit extensions, e.g.: | 817 /* Also check operations with implicit extensions, e.g.: |
792 [(set (reg:DI) | 818 [(set (reg:DI) |
793 (zero_extend:DI (plus:SI (reg:SI) (reg:SI)))) | 819 (zero_extend:DI (plus:SI (reg:SI) (reg:SI)))) |
794 (set (reg:CCZ flags) | 820 (set (reg:CCZ flags) |
798 && REG_P (in_a) | 824 && REG_P (in_a) |
799 && REGNO (SET_DEST (x)) == REGNO (in_a) | 825 && REGNO (SET_DEST (x)) == REGNO (in_a) |
800 && (GET_CODE (SET_SRC (x)) == ZERO_EXTEND | 826 && (GET_CODE (SET_SRC (x)) == ZERO_EXTEND |
801 || GET_CODE (SET_SRC (x)) == SIGN_EXTEND) | 827 || GET_CODE (SET_SRC (x)) == SIGN_EXTEND) |
802 && GET_MODE (XEXP (SET_SRC (x), 0)) == GET_MODE (in_a)) | 828 && GET_MODE (XEXP (SET_SRC (x), 0)) == GET_MODE (in_a)) |
803 cmp_src = XEXP (SET_SRC (x), 0); | 829 cmp_a = XEXP (SET_SRC (x), 0); |
804 | 830 |
805 /* Also check fully redundant comparisons, e.g.: | 831 /* Also check fully redundant comparisons, e.g.: |
806 [(set (reg:SI) | 832 [(set (reg:SI) |
807 (minus:SI (reg:SI) (reg:SI)))) | 833 (minus:SI (reg:SI) (reg:SI)))) |
808 (set (reg:CC flags) | 834 (set (reg:CC flags) |
809 (compare:CC (reg:SI) (reg:SI)))] */ | 835 (compare:CC (reg:SI) (reg:SI)))] */ |
810 else if (REG_P (in_b) | 836 else if (REG_P (in_b) |
811 && GET_CODE (SET_SRC (x)) == MINUS | 837 && GET_CODE (SET_SRC (x)) == MINUS |
812 && rtx_equal_p (XEXP (SET_SRC (x), 0), in_a) | 838 && rtx_equal_p (XEXP (SET_SRC (x), 0), in_a) |
813 && rtx_equal_p (XEXP (SET_SRC (x), 1), in_b)) | 839 && rtx_equal_p (XEXP (SET_SRC (x), 1), in_b)) |
814 cmp_src = in_a; | 840 cmp_a = in_a; |
815 | 841 |
816 else | 842 else |
817 return false; | 843 return false; |
818 | 844 |
819 /* If the source uses addressing modes with side effects, we can't | 845 /* 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 | 846 do the merge because we'd end up with a PARALLEL that has two |
821 instances of that side effect in it. */ | 847 instances of that side effect in it. */ |
822 if (side_effects_p (cmp_src)) | 848 if (side_effects_p (cmp_a)) |
849 return false; | |
850 | |
851 if (in_a == in_b) | |
852 cmp_b = cmp_a; | |
853 else if (rtx_equal_p (SET_DEST (x), in_b)) | |
854 cmp_b = SET_SRC (x); | |
855 else | |
856 cmp_b = in_b; | |
857 if (side_effects_p (cmp_b)) | |
823 return false; | 858 return false; |
824 | 859 |
825 /* Determine if we ought to use a different CC_MODE here. */ | 860 /* Determine if we ought to use a different CC_MODE here. */ |
826 flags = maybe_select_cc_mode (cmp, cmp_src, in_b); | 861 flags = maybe_select_cc_mode (cmp, cmp_a, cmp_b); |
827 if (flags == NULL) | 862 if (flags == NULL) |
828 flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum); | 863 flags = gen_rtx_REG (cmp->orig_mode, targetm.flags_regnum); |
829 | 864 |
830 /* Generate a new comparison for installation in the setter. */ | 865 /* Generate a new comparison for installation in the setter. */ |
831 rtx y = copy_rtx (cmp_src); | 866 rtx y = cmp->not_in_a |
832 y = gen_rtx_COMPARE (GET_MODE (flags), y, in_b); | 867 ? gen_rtx_NOT (GET_MODE (cmp_a), copy_rtx (cmp_a)) |
868 : copy_rtx (cmp_a); | |
869 y = gen_rtx_COMPARE (GET_MODE (flags), y, copy_rtx (cmp_b)); | |
833 y = gen_rtx_SET (flags, y); | 870 y = gen_rtx_SET (flags, y); |
834 | 871 |
835 /* Canonicalize instruction to: | 872 /* Canonicalize instruction to: |
836 [(set (reg:CCM) (compare:CCM (operation) (immediate))) | 873 [(set (reg:CCM) (compare:CCM (operation) (immediate))) |
837 (set (reg) (operation)] */ | 874 (set (reg) (operation)] */ |