Mercurial > hg > CbC > CbC_gcc
comparison gcc/auto-inc-dec.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 /* Discovery of auto-inc and auto-dec instructions. | 1 /* Discovery of auto-inc and auto-dec instructions. |
2 Copyright (C) 2006-2017 Free Software Foundation, Inc. | 2 Copyright (C) 2006-2018 Free Software Foundation, Inc. |
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> | 3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it under | 7 GCC is free software; you can redistribute it and/or modify it under |
150 | 150 |
151 /* Tmp mem rtx for use in cost modeling. */ | 151 /* Tmp mem rtx for use in cost modeling. */ |
152 static rtx mem_tmp; | 152 static rtx mem_tmp; |
153 | 153 |
154 static enum inc_state | 154 static enum inc_state |
155 set_inc_state (HOST_WIDE_INT val, int size) | 155 set_inc_state (HOST_WIDE_INT val, poly_int64 size) |
156 { | 156 { |
157 if (val == 0) | 157 if (val == 0) |
158 return INC_ZERO; | 158 return INC_ZERO; |
159 if (val < 0) | 159 if (val < 0) |
160 return (val == -size) ? INC_NEG_SIZE : INC_NEG_ANY; | 160 return known_eq (val, -size) ? INC_NEG_SIZE : INC_NEG_ANY; |
161 else | 161 else |
162 return (val == size) ? INC_POS_SIZE : INC_POS_ANY; | 162 return known_eq (val, size) ? INC_POS_SIZE : INC_POS_ANY; |
163 } | 163 } |
164 | 164 |
165 /* The DECISION_TABLE that describes what form, if any, the increment | 165 /* The DECISION_TABLE that describes what form, if any, the increment |
166 or decrement will take. It is a three dimensional table. The first | 166 or decrement will take. It is a three dimensional table. The first |
167 index is the type of constant or register found as the second | 167 index is the type of constant or register found as the second |
506 /* Replace the addition with a move. Do it at the location of | 506 /* Replace the addition with a move. Do it at the location of |
507 the addition since the operand of the addition may change | 507 the addition since the operand of the addition may change |
508 before the memory reference. */ | 508 before the memory reference. */ |
509 gcc_assert (mov_insn); | 509 gcc_assert (mov_insn); |
510 emit_insn_before (mov_insn, inc_insn.insn); | 510 emit_insn_before (mov_insn, inc_insn.insn); |
511 move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0); | 511 regno = REGNO (inc_insn.reg0); |
512 if (reg_next_use[regno] == mem_insn.insn) | |
513 move_dead_notes (mov_insn, mem_insn.insn, inc_insn.reg0); | |
514 else | |
515 move_dead_notes (mov_insn, inc_insn.insn, inc_insn.reg0); | |
512 | 516 |
513 regno = REGNO (inc_insn.reg_res); | 517 regno = REGNO (inc_insn.reg_res); |
514 reg_next_def[regno] = mov_insn; | 518 reg_next_def[regno] = mov_insn; |
515 reg_next_use[regno] = NULL; | 519 reg_next_use[regno] = NULL; |
516 regno = REGNO (inc_insn.reg0); | 520 regno = REGNO (inc_insn.reg0); |
599 rtx mem = *mem_insn.mem_loc; | 603 rtx mem = *mem_insn.mem_loc; |
600 rtx inc_reg = inc_insn.form == FORM_POST_ADD ? | 604 rtx inc_reg = inc_insn.form == FORM_POST_ADD ? |
601 inc_insn.reg_res : mem_insn.reg0; | 605 inc_insn.reg_res : mem_insn.reg0; |
602 | 606 |
603 /* The width of the mem being accessed. */ | 607 /* The width of the mem being accessed. */ |
604 int size = GET_MODE_SIZE (GET_MODE (mem)); | 608 poly_int64 size = GET_MODE_SIZE (GET_MODE (mem)); |
605 rtx_insn *last_insn = NULL; | 609 rtx_insn *last_insn = NULL; |
606 machine_mode reg_mode = GET_MODE (inc_reg); | 610 machine_mode reg_mode = GET_MODE (inc_reg); |
607 | 611 |
608 switch (inc_insn.form) | 612 switch (inc_insn.form) |
609 { | 613 { |
823 } | 827 } |
824 | 828 |
825 | 829 |
826 /* A recursive function that checks all of the mem uses in | 830 /* A recursive function that checks all of the mem uses in |
827 ADDRESS_OF_X to see if any single one of them is compatible with | 831 ADDRESS_OF_X to see if any single one of them is compatible with |
828 what has been found in inc_insn. | 832 what has been found in inc_insn. To avoid accidental matches, we |
833 will only find MEMs with FINDREG, be it inc_insn.reg_res, be it | |
834 inc_insn.reg0. | |
829 | 835 |
830 -1 is returned for success. 0 is returned if nothing was found and | 836 -1 is returned for success. 0 is returned if nothing was found and |
831 1 is returned for failure. */ | 837 1 is returned for failure. */ |
832 | 838 |
833 static int | 839 static int |
834 find_address (rtx *address_of_x) | 840 find_address (rtx *address_of_x, rtx findreg) |
835 { | 841 { |
836 rtx x = *address_of_x; | 842 rtx x = *address_of_x; |
837 enum rtx_code code = GET_CODE (x); | 843 enum rtx_code code = GET_CODE (x); |
838 const char *const fmt = GET_RTX_FORMAT (code); | 844 const char *const fmt = GET_RTX_FORMAT (code); |
839 int i; | 845 int i; |
840 int value = 0; | 846 int value = 0; |
841 int tem; | 847 int tem; |
842 | 848 |
843 if (code == MEM && rtx_equal_p (XEXP (x, 0), inc_insn.reg_res)) | 849 if (code == MEM && findreg == inc_insn.reg_res |
844 { | 850 && rtx_equal_p (XEXP (x, 0), inc_insn.reg_res)) |
845 /* Match with *reg0. */ | 851 { |
852 /* Match with *reg_res. */ | |
846 mem_insn.mem_loc = address_of_x; | 853 mem_insn.mem_loc = address_of_x; |
847 mem_insn.reg0 = inc_insn.reg_res; | 854 mem_insn.reg0 = inc_insn.reg_res; |
848 mem_insn.reg1_is_const = true; | 855 mem_insn.reg1_is_const = true; |
849 mem_insn.reg1_val = 0; | 856 mem_insn.reg1_val = 0; |
850 mem_insn.reg1 = GEN_INT (0); | 857 mem_insn.reg1 = GEN_INT (0); |
851 return -1; | 858 return -1; |
852 } | 859 } |
853 if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS | 860 if (code == MEM && inc_insn.reg1_is_const && inc_insn.reg0 |
861 && findreg == inc_insn.reg0 | |
862 && rtx_equal_p (XEXP (x, 0), inc_insn.reg0)) | |
863 { | |
864 /* Match with *reg0, assumed to be equivalent to | |
865 *(reg_res - reg1_val); callers must check whether this is the case. */ | |
866 mem_insn.mem_loc = address_of_x; | |
867 mem_insn.reg0 = inc_insn.reg_res; | |
868 mem_insn.reg1_is_const = true; | |
869 mem_insn.reg1_val = -inc_insn.reg1_val; | |
870 mem_insn.reg1 = GEN_INT (mem_insn.reg1_val); | |
871 return -1; | |
872 } | |
873 if (code == MEM && findreg == inc_insn.reg_res | |
874 && GET_CODE (XEXP (x, 0)) == PLUS | |
854 && rtx_equal_p (XEXP (XEXP (x, 0), 0), inc_insn.reg_res)) | 875 && rtx_equal_p (XEXP (XEXP (x, 0), 0), inc_insn.reg_res)) |
855 { | 876 { |
856 rtx b = XEXP (XEXP (x, 0), 1); | 877 rtx b = XEXP (XEXP (x, 0), 1); |
857 mem_insn.mem_loc = address_of_x; | 878 mem_insn.mem_loc = address_of_x; |
858 mem_insn.reg0 = inc_insn.reg_res; | 879 mem_insn.reg0 = inc_insn.reg_res; |
877 | 898 |
878 if (code == SIGN_EXTRACT || code == ZERO_EXTRACT) | 899 if (code == SIGN_EXTRACT || code == ZERO_EXTRACT) |
879 { | 900 { |
880 /* If REG occurs inside a MEM used in a bit-field reference, | 901 /* If REG occurs inside a MEM used in a bit-field reference, |
881 that is unacceptable. */ | 902 that is unacceptable. */ |
882 if (find_address (&XEXP (x, 0))) | 903 if (find_address (&XEXP (x, 0), findreg)) |
883 return 1; | 904 return 1; |
884 } | 905 } |
885 | 906 |
886 if (x == inc_insn.reg_res) | 907 if (x == inc_insn.reg_res) |
887 return 1; | 908 return 1; |
889 /* Time for some deep diving. */ | 910 /* Time for some deep diving. */ |
890 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | 911 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) |
891 { | 912 { |
892 if (fmt[i] == 'e') | 913 if (fmt[i] == 'e') |
893 { | 914 { |
894 tem = find_address (&XEXP (x, i)); | 915 tem = find_address (&XEXP (x, i), findreg); |
895 /* If this is the first use, let it go so the rest of the | 916 /* If this is the first use, let it go so the rest of the |
896 insn can be checked. */ | 917 insn can be checked. */ |
897 if (value == 0) | 918 if (value == 0) |
898 value = tem; | 919 value = tem; |
899 else if (tem != 0) | 920 else if (tem != 0) |
903 else if (fmt[i] == 'E') | 924 else if (fmt[i] == 'E') |
904 { | 925 { |
905 int j; | 926 int j; |
906 for (j = XVECLEN (x, i) - 1; j >= 0; j--) | 927 for (j = XVECLEN (x, i) - 1; j >= 0; j--) |
907 { | 928 { |
908 tem = find_address (&XVECEXP (x, i, j)); | 929 tem = find_address (&XVECEXP (x, i, j), findreg); |
909 /* If this is the first use, let it go so the rest of | 930 /* If this is the first use, let it go so the rest of |
910 the insn can be checked. */ | 931 the insn can be checked. */ |
911 if (value == 0) | 932 if (value == 0) |
912 value = tem; | 933 value = tem; |
913 else if (tem != 0) | 934 else if (tem != 0) |
1358 } | 1379 } |
1359 | 1380 |
1360 if (dump_file) | 1381 if (dump_file) |
1361 dump_inc_insn (dump_file); | 1382 dump_inc_insn (dump_file); |
1362 | 1383 |
1363 if (ok && find_address (&PATTERN (mem_insn.insn)) == -1) | 1384 if (ok && find_address (&PATTERN (mem_insn.insn), |
1385 inc_insn.reg_res) == -1) | |
1386 { | |
1387 if (dump_file) | |
1388 dump_mem_insn (dump_file); | |
1389 if (try_merge ()) | |
1390 { | |
1391 success_in_block++; | |
1392 insn_is_add_or_inc = false; | |
1393 } | |
1394 } | |
1395 } | |
1396 | |
1397 if (insn_is_add_or_inc | |
1398 /* find_address will only recognize an address | |
1399 with a reg0 that's not reg_res when | |
1400 reg1_is_const, so cut it off early if we | |
1401 already know it won't match. */ | |
1402 && inc_insn.reg1_is_const | |
1403 && inc_insn.reg0 | |
1404 && inc_insn.reg0 != inc_insn.reg_res) | |
1405 { | |
1406 /* If we identified an inc_insn that uses two | |
1407 different pseudos, it's of the form | |
1408 | |
1409 (set reg_res (plus reg0 reg1)) | |
1410 | |
1411 where reg1 is a constant (*). | |
1412 | |
1413 The next use of reg_res was not idenfied by | |
1414 find_address as a mem_insn that we could turn | |
1415 into auto-inc, so see if we find a suitable | |
1416 MEM in the next use of reg0, as long as it's | |
1417 before any subsequent use of reg_res: | |
1418 | |
1419 ... (mem (... reg0 ...)) ... | |
1420 | |
1421 ... reg_res ... | |
1422 | |
1423 In this case, we can turn the plus into a | |
1424 copy, and the reg0 in the MEM address into a | |
1425 post_inc of reg_res: | |
1426 | |
1427 (set reg_res reg0) | |
1428 | |
1429 ... (mem (... (post_add reg_res reg1) ...)) ... | |
1430 | |
1431 reg_res will then have the correct value at | |
1432 subsequent uses, and reg0 will remain | |
1433 unchanged. | |
1434 | |
1435 (*) We could support non-const reg1, but then | |
1436 we'd have to check that reg1 remains | |
1437 unchanged all the way to the modified MEM, | |
1438 and we'd have to extend find_address to | |
1439 represent a non-const negated reg1. */ | |
1440 regno = REGNO (inc_insn.reg0); | |
1441 rtx_insn *reg0_use = get_next_ref (regno, bb, | |
1442 reg_next_use); | |
1443 | |
1444 /* Give up if the next use of reg0 is after the next | |
1445 use of reg_res (same insn is ok; we might have | |
1446 found a MEM with reg_res before, and that failed, | |
1447 but now we try reg0, which might work), or defs | |
1448 of reg_res (same insn is not ok, we'd introduce | |
1449 another def in the same insn) or reg0. */ | |
1450 if (reg0_use) | |
1451 { | |
1452 int luid = DF_INSN_LUID (reg0_use); | |
1453 | |
1454 /* It might seem pointless to introduce an | |
1455 auto-inc if there's no subsequent use of | |
1456 reg_res (i.e., mem_insn.insn == NULL), but | |
1457 the next use might be in the next iteration | |
1458 of a loop, and it won't hurt if we make the | |
1459 change even if it's not needed. */ | |
1460 if (mem_insn.insn | |
1461 && luid > DF_INSN_LUID (mem_insn.insn)) | |
1462 reg0_use = NULL; | |
1463 | |
1464 rtx_insn *other_insn | |
1465 = get_next_ref (REGNO (inc_insn.reg_res), bb, | |
1466 reg_next_def); | |
1467 | |
1468 if (other_insn && luid >= DF_INSN_LUID (other_insn)) | |
1469 reg0_use = NULL; | |
1470 | |
1471 other_insn | |
1472 = get_next_ref (REGNO (inc_insn.reg0), bb, | |
1473 reg_next_def); | |
1474 | |
1475 if (other_insn && luid > DF_INSN_LUID (other_insn)) | |
1476 reg0_use = NULL; | |
1477 } | |
1478 | |
1479 mem_insn.insn = reg0_use; | |
1480 | |
1481 if (mem_insn.insn | |
1482 && find_address (&PATTERN (mem_insn.insn), | |
1483 inc_insn.reg0) == -1) | |
1364 { | 1484 { |
1365 if (dump_file) | 1485 if (dump_file) |
1366 dump_mem_insn (dump_file); | 1486 dump_mem_insn (dump_file); |
1367 if (try_merge ()) | 1487 if (try_merge ()) |
1368 { | 1488 { |