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)] */