Mercurial > hg > CbC > CbC_gcc
comparison gcc/recog.c @ 55:77e2b8dfacca gcc-4.4.5
update it from 4.4.3 to 4.5.0
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 12 Feb 2010 23:39:51 +0900 |
parents | a06113de4d67 |
children | b7f97abdc517 |
comparison
equal
deleted
inserted
replaced
52:c156f1bd5cd9 | 55:77e2b8dfacca |
---|---|
284 return true; | 284 return true; |
285 } | 285 } |
286 else | 286 else |
287 return false; | 287 return false; |
288 } | 288 } |
289 | 289 |
290 | 290 |
291 /* This subroutine of apply_change_group verifies whether the changes to INSN | 291 /* This subroutine of apply_change_group verifies whether the changes to INSN |
292 were valid; i.e. whether INSN can still be recognized. */ | 292 were valid; i.e. whether INSN can still be recognized. */ |
293 | 293 |
294 int | 294 int |
374 if (object == 0 || object == last_validated) | 374 if (object == 0 || object == last_validated) |
375 continue; | 375 continue; |
376 | 376 |
377 if (MEM_P (object)) | 377 if (MEM_P (object)) |
378 { | 378 { |
379 if (! memory_address_p (GET_MODE (object), XEXP (object, 0))) | 379 if (! memory_address_addr_space_p (GET_MODE (object), |
380 XEXP (object, 0), | |
381 MEM_ADDR_SPACE (object))) | |
380 break; | 382 break; |
381 } | 383 } |
382 else if (REG_P (changes[i].old) | 384 else if (REG_P (changes[i].old) |
383 && asm_noperands (PATTERN (object)) > 0 | 385 && asm_noperands (PATTERN (object)) > 0 |
384 && REG_EXPR (changes[i].old) != NULL_TREE | 386 && REG_EXPR (changes[i].old) != NULL_TREE |
387 { | 389 { |
388 /* Don't allow changes of hard register operands to inline | 390 /* Don't allow changes of hard register operands to inline |
389 assemblies if they have been defined as register asm ("x"). */ | 391 assemblies if they have been defined as register asm ("x"). */ |
390 break; | 392 break; |
391 } | 393 } |
394 else if (DEBUG_INSN_P (object)) | |
395 continue; | |
392 else if (insn_invalid_p (object)) | 396 else if (insn_invalid_p (object)) |
393 { | 397 { |
394 rtx pat = PATTERN (object); | 398 rtx pat = PATTERN (object); |
395 | 399 |
396 /* Perhaps we couldn't recognize the insn because there were | 400 /* Perhaps we couldn't recognize the insn because there were |
427 but this shouldn't occur. */ | 431 but this shouldn't occur. */ |
428 | 432 |
429 validate_change (object, &PATTERN (object), newpat, 1); | 433 validate_change (object, &PATTERN (object), newpat, 1); |
430 continue; | 434 continue; |
431 } | 435 } |
432 else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER) | 436 else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER |
437 || GET_CODE (pat) == VAR_LOCATION) | |
433 /* If this insn is a CLOBBER or USE, it is always valid, but is | 438 /* If this insn is a CLOBBER or USE, it is always valid, but is |
434 never recognized. */ | 439 never recognized. */ |
435 continue; | 440 continue; |
436 else | 441 else |
437 break; | 442 break; |
522 | 527 |
523 /* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting | 528 /* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting |
524 rtx. */ | 529 rtx. */ |
525 | 530 |
526 static void | 531 static void |
527 simplify_while_replacing (rtx *loc, rtx to, rtx object, | 532 simplify_while_replacing (rtx *loc, rtx to, rtx object, |
528 enum machine_mode op0_mode) | 533 enum machine_mode op0_mode) |
529 { | 534 { |
530 rtx x = *loc; | 535 rtx x = *loc; |
531 enum rtx_code code = GET_CODE (x); | 536 enum rtx_code code = GET_CODE (x); |
532 rtx new_rtx; | 537 rtx new_rtx; |
548 case PLUS: | 553 case PLUS: |
549 /* If we have a PLUS whose second operand is now a CONST_INT, use | 554 /* If we have a PLUS whose second operand is now a CONST_INT, use |
550 simplify_gen_binary to try to simplify it. | 555 simplify_gen_binary to try to simplify it. |
551 ??? We may want later to remove this, once simplification is | 556 ??? We may want later to remove this, once simplification is |
552 separated from this function. */ | 557 separated from this function. */ |
553 if (GET_CODE (XEXP (x, 1)) == CONST_INT && XEXP (x, 1) == to) | 558 if (CONST_INT_P (XEXP (x, 1)) && XEXP (x, 1) == to) |
554 validate_change (object, loc, | 559 validate_change (object, loc, |
555 simplify_gen_binary | 560 simplify_gen_binary |
556 (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1); | 561 (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1); |
557 break; | 562 break; |
558 case MINUS: | 563 case MINUS: |
559 if (GET_CODE (XEXP (x, 1)) == CONST_INT | 564 if (CONST_INT_P (XEXP (x, 1)) |
560 || GET_CODE (XEXP (x, 1)) == CONST_DOUBLE) | 565 || GET_CODE (XEXP (x, 1)) == CONST_DOUBLE) |
561 validate_change (object, loc, | 566 validate_change (object, loc, |
562 simplify_gen_binary | 567 simplify_gen_binary |
563 (PLUS, GET_MODE (x), XEXP (x, 0), | 568 (PLUS, GET_MODE (x), XEXP (x, 0), |
564 simplify_gen_unary (NEG, | 569 simplify_gen_unary (NEG, |
595 to be the mode required for memory in extract operations (this isn't | 600 to be the mode required for memory in extract operations (this isn't |
596 likely to be an insertion operation; if it was, nothing bad will | 601 likely to be an insertion operation; if it was, nothing bad will |
597 happen, we might just fail in some cases). */ | 602 happen, we might just fail in some cases). */ |
598 | 603 |
599 if (MEM_P (XEXP (x, 0)) | 604 if (MEM_P (XEXP (x, 0)) |
600 && GET_CODE (XEXP (x, 1)) == CONST_INT | 605 && CONST_INT_P (XEXP (x, 1)) |
601 && GET_CODE (XEXP (x, 2)) == CONST_INT | 606 && CONST_INT_P (XEXP (x, 2)) |
602 && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0)) | 607 && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0)) |
603 && !MEM_VOLATILE_P (XEXP (x, 0))) | 608 && !MEM_VOLATILE_P (XEXP (x, 0))) |
604 { | 609 { |
605 enum machine_mode wanted_mode = VOIDmode; | 610 enum machine_mode wanted_mode = VOIDmode; |
606 enum machine_mode is_mode = GET_MODE (XEXP (x, 0)); | 611 enum machine_mode is_mode = GET_MODE (XEXP (x, 0)); |
653 | 658 |
654 /* Replace every occurrence of FROM in X with TO. Mark each change with | 659 /* Replace every occurrence of FROM in X with TO. Mark each change with |
655 validate_change passing OBJECT. */ | 660 validate_change passing OBJECT. */ |
656 | 661 |
657 static void | 662 static void |
658 validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object, | 663 validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object, |
659 bool simplify) | 664 bool simplify) |
660 { | 665 { |
661 int i, j; | 666 int i, j; |
662 const char *fmt; | 667 const char *fmt; |
663 rtx x = *loc; | 668 rtx x = *loc; |
706 (x, 0, j)))); | 711 (x, 0, j)))); |
707 validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)), | 712 validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)), |
708 from, to, object, simplify); | 713 from, to, object, simplify); |
709 } | 714 } |
710 else | 715 else |
711 validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object, | 716 validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object, |
712 simplify); | 717 simplify); |
713 } | 718 } |
714 } | 719 } |
715 else | 720 else |
716 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) | 721 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) |
717 { | 722 { |
718 if (fmt[i] == 'e') | 723 if (fmt[i] == 'e') |
719 validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify); | 724 validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify); |
720 else if (fmt[i] == 'E') | 725 else if (fmt[i] == 'E') |
721 for (j = XVECLEN (x, i) - 1; j >= 0; j--) | 726 for (j = XVECLEN (x, i) - 1; j >= 0; j--) |
722 validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object, | 727 validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object, |
723 simplify); | 728 simplify); |
724 } | 729 } |
725 | 730 |
726 /* If we didn't substitute, there is nothing more to do. */ | 731 /* If we didn't substitute, there is nothing more to do. */ |
727 if (num_changes == prev_changes) | 732 if (num_changes == prev_changes) |
736 simplifications, as it is not our job. */ | 741 simplifications, as it is not our job. */ |
737 if (simplify) | 742 if (simplify) |
738 simplify_while_replacing (loc, to, object, op0_mode); | 743 simplify_while_replacing (loc, to, object, op0_mode); |
739 } | 744 } |
740 | 745 |
746 /* Try replacing every occurrence of FROM in subexpression LOC of INSN | |
747 with TO. After all changes have been made, validate by seeing | |
748 if INSN is still valid. */ | |
749 | |
750 int | |
751 validate_replace_rtx_subexp (rtx from, rtx to, rtx insn, rtx *loc) | |
752 { | |
753 validate_replace_rtx_1 (loc, from, to, insn, true); | |
754 return apply_change_group (); | |
755 } | |
756 | |
741 /* Try replacing every occurrence of FROM in INSN with TO. After all | 757 /* Try replacing every occurrence of FROM in INSN with TO. After all |
742 changes have been made, validate by seeing if INSN is still valid. */ | 758 changes have been made, validate by seeing if INSN is still valid. */ |
743 | 759 |
744 int | 760 int |
745 validate_replace_rtx (rtx from, rtx to, rtx insn) | 761 validate_replace_rtx (rtx from, rtx to, rtx insn) |
747 validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true); | 763 validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true); |
748 return apply_change_group (); | 764 return apply_change_group (); |
749 } | 765 } |
750 | 766 |
751 /* Try replacing every occurrence of FROM in WHERE with TO. Assume that WHERE | 767 /* Try replacing every occurrence of FROM in WHERE with TO. Assume that WHERE |
752 is a part of INSN. After all changes have been made, validate by seeing if | 768 is a part of INSN. After all changes have been made, validate by seeing if |
753 INSN is still valid. | 769 INSN is still valid. |
754 validate_replace_rtx (from, to, insn) is equivalent to | 770 validate_replace_rtx (from, to, insn) is equivalent to |
755 validate_replace_rtx_part (from, to, &PATTERN (insn), insn). */ | 771 validate_replace_rtx_part (from, to, &PATTERN (insn), insn). */ |
756 | 772 |
757 int | 773 int |
758 validate_replace_rtx_part (rtx from, rtx to, rtx *where, rtx insn) | 774 validate_replace_rtx_part (rtx from, rtx to, rtx *where, rtx insn) |
759 { | 775 { |
760 validate_replace_rtx_1 (where, from, to, insn, true); | 776 validate_replace_rtx_1 (where, from, to, insn, true); |
761 return apply_change_group (); | 777 return apply_change_group (); |
762 } | 778 } |
763 | 779 |
764 /* Same as above, but do not simplify rtx afterwards. */ | 780 /* Same as above, but do not simplify rtx afterwards. */ |
765 int | 781 int |
766 validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where, | 782 validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where, |
767 rtx insn) | 783 rtx insn) |
768 { | 784 { |
769 validate_replace_rtx_1 (where, from, to, insn, false); | 785 validate_replace_rtx_1 (where, from, to, insn, false); |
770 return apply_change_group (); | 786 return apply_change_group (); |
771 | 787 |
899 if (GET_MODE (op) == VOIDmode && mode != VOIDmode | 915 if (GET_MODE (op) == VOIDmode && mode != VOIDmode |
900 && GET_MODE_CLASS (mode) != MODE_INT | 916 && GET_MODE_CLASS (mode) != MODE_INT |
901 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) | 917 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) |
902 return 0; | 918 return 0; |
903 | 919 |
904 if (GET_CODE (op) == CONST_INT | 920 if (CONST_INT_P (op) |
905 && mode != VOIDmode | 921 && mode != VOIDmode |
906 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) | 922 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) |
907 return 0; | 923 return 0; |
908 | 924 |
909 if (CONSTANT_P (op)) | 925 if (CONSTANT_P (op)) |
962 | 978 |
963 if (! volatile_ok && MEM_VOLATILE_P (op)) | 979 if (! volatile_ok && MEM_VOLATILE_P (op)) |
964 return 0; | 980 return 0; |
965 | 981 |
966 /* Use the mem's mode, since it will be reloaded thus. */ | 982 /* Use the mem's mode, since it will be reloaded thus. */ |
967 if (memory_address_p (GET_MODE (op), y)) | 983 if (memory_address_addr_space_p (GET_MODE (op), y, MEM_ADDR_SPACE (op))) |
968 return 1; | 984 return 1; |
969 } | 985 } |
970 | 986 |
971 return 0; | 987 return 0; |
972 } | 988 } |
1076 if (GET_MODE (op) == VOIDmode && mode != VOIDmode | 1092 if (GET_MODE (op) == VOIDmode && mode != VOIDmode |
1077 && GET_MODE_CLASS (mode) != MODE_INT | 1093 && GET_MODE_CLASS (mode) != MODE_INT |
1078 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) | 1094 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) |
1079 return 0; | 1095 return 0; |
1080 | 1096 |
1081 if (GET_CODE (op) == CONST_INT | 1097 if (CONST_INT_P (op) |
1082 && mode != VOIDmode | 1098 && mode != VOIDmode |
1083 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) | 1099 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) |
1084 return 0; | 1100 return 0; |
1085 | 1101 |
1086 return (CONSTANT_P (op) | 1102 return (CONSTANT_P (op) |
1093 /* Returns 1 if OP is an operand that is a CONST_INT. */ | 1109 /* Returns 1 if OP is an operand that is a CONST_INT. */ |
1094 | 1110 |
1095 int | 1111 int |
1096 const_int_operand (rtx op, enum machine_mode mode) | 1112 const_int_operand (rtx op, enum machine_mode mode) |
1097 { | 1113 { |
1098 if (GET_CODE (op) != CONST_INT) | 1114 if (!CONST_INT_P (op)) |
1099 return 0; | 1115 return 0; |
1100 | 1116 |
1101 if (mode != VOIDmode | 1117 if (mode != VOIDmode |
1102 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) | 1118 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) |
1103 return 0; | 1119 return 0; |
1116 if (GET_MODE (op) == VOIDmode && mode != VOIDmode | 1132 if (GET_MODE (op) == VOIDmode && mode != VOIDmode |
1117 && GET_MODE_CLASS (mode) != MODE_INT | 1133 && GET_MODE_CLASS (mode) != MODE_INT |
1118 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) | 1134 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) |
1119 return 0; | 1135 return 0; |
1120 | 1136 |
1121 return ((GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT) | 1137 return ((GET_CODE (op) == CONST_DOUBLE || CONST_INT_P (op)) |
1122 && (mode == VOIDmode || GET_MODE (op) == mode | 1138 && (mode == VOIDmode || GET_MODE (op) == mode |
1123 || GET_MODE (op) == VOIDmode)); | 1139 || GET_MODE (op) == VOIDmode)); |
1124 } | 1140 } |
1125 | 1141 |
1126 /* Return 1 if OP is a general operand that is not an immediate operand. */ | 1142 /* Return 1 if OP is a general operand that is not an immediate operand. */ |
1143 if (GET_MODE (op) == VOIDmode && mode != VOIDmode | 1159 if (GET_MODE (op) == VOIDmode && mode != VOIDmode |
1144 && GET_MODE_CLASS (mode) != MODE_INT | 1160 && GET_MODE_CLASS (mode) != MODE_INT |
1145 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) | 1161 && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) |
1146 return 0; | 1162 return 0; |
1147 | 1163 |
1148 if (GET_CODE (op) == CONST_INT | 1164 if (CONST_INT_P (op) |
1149 && mode != VOIDmode | 1165 && mode != VOIDmode |
1150 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) | 1166 && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op)) |
1151 return 0; | 1167 return 0; |
1152 | 1168 |
1153 return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode | 1169 return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode |
1210 else | 1226 else |
1211 { | 1227 { |
1212 if (GET_CODE (op) != PRE_MODIFY | 1228 if (GET_CODE (op) != PRE_MODIFY |
1213 || GET_CODE (XEXP (op, 1)) != PLUS | 1229 || GET_CODE (XEXP (op, 1)) != PLUS |
1214 || XEXP (XEXP (op, 1), 0) != XEXP (op, 0) | 1230 || XEXP (XEXP (op, 1), 0) != XEXP (op, 0) |
1215 || GET_CODE (XEXP (XEXP (op, 1), 1)) != CONST_INT | 1231 || !CONST_INT_P (XEXP (XEXP (op, 1), 1)) |
1216 #ifdef STACK_GROWS_DOWNWARD | 1232 #ifdef STACK_GROWS_DOWNWARD |
1217 || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size | 1233 || INTVAL (XEXP (XEXP (op, 1), 1)) != - (int) rounded_size |
1218 #else | 1234 #else |
1219 || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size | 1235 || INTVAL (XEXP (XEXP (op, 1), 1)) != (int) rounded_size |
1220 #endif | 1236 #endif |
1246 return 0; | 1262 return 0; |
1247 | 1263 |
1248 return XEXP (op, 0) == stack_pointer_rtx; | 1264 return XEXP (op, 0) == stack_pointer_rtx; |
1249 } | 1265 } |
1250 | 1266 |
1251 /* Return 1 if ADDR is a valid memory address for mode MODE. */ | 1267 /* Return 1 if ADDR is a valid memory address |
1252 | 1268 for mode MODE in address space AS. */ |
1253 int | 1269 |
1254 memory_address_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx addr) | 1270 int |
1255 { | 1271 memory_address_addr_space_p (enum machine_mode mode ATTRIBUTE_UNUSED, |
1272 rtx addr, addr_space_t as) | |
1273 { | |
1274 #ifdef GO_IF_LEGITIMATE_ADDRESS | |
1275 gcc_assert (ADDR_SPACE_GENERIC_P (as)); | |
1256 GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); | 1276 GO_IF_LEGITIMATE_ADDRESS (mode, addr, win); |
1257 return 0; | 1277 return 0; |
1258 | 1278 |
1259 win: | 1279 win: |
1260 return 1; | 1280 return 1; |
1281 #else | |
1282 return targetm.addr_space.legitimate_address_p (mode, addr, 0, as); | |
1283 #endif | |
1261 } | 1284 } |
1262 | 1285 |
1263 /* Return 1 if OP is a valid memory reference with mode MODE, | 1286 /* Return 1 if OP is a valid memory reference with mode MODE, |
1264 including a valid address. | 1287 including a valid address. |
1265 | 1288 |
1307 or if the address is (plus Y (const_int -OFFSET)) and Y is an | 1330 or if the address is (plus Y (const_int -OFFSET)) and Y is an |
1308 operand. */ | 1331 operand. */ |
1309 | 1332 |
1310 return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode)) | 1333 return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode)) |
1311 || (GET_CODE (XEXP (inner, 0)) == PLUS | 1334 || (GET_CODE (XEXP (inner, 0)) == PLUS |
1312 && GET_CODE (XEXP (XEXP (inner, 0), 1)) == CONST_INT | 1335 && CONST_INT_P (XEXP (XEXP (inner, 0), 1)) |
1313 && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset | 1336 && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset |
1314 && general_operand (XEXP (XEXP (inner, 0), 0), Pmode))); | 1337 && general_operand (XEXP (XEXP (inner, 0), 0), Pmode))); |
1315 } | 1338 } |
1316 | 1339 |
1317 return (MEM_P (op) | 1340 return (MEM_P (op) |
1318 && memory_operand (op, mode) | 1341 && memory_operand (op, mode) |
1319 && general_operand (XEXP (op, 0), Pmode)); | 1342 && general_operand (XEXP (op, 0), Pmode)); |
1320 } | 1343 } |
1321 | 1344 |
1345 /* Return 1 if this is an ordered comparison operator (not including | |
1346 ORDERED and UNORDERED). */ | |
1347 | |
1348 int | |
1349 ordered_comparison_operator (rtx op, enum machine_mode mode) | |
1350 { | |
1351 if (mode != VOIDmode && GET_MODE (op) != mode) | |
1352 return false; | |
1353 switch (GET_CODE (op)) | |
1354 { | |
1355 case EQ: | |
1356 case NE: | |
1357 case LT: | |
1358 case LTU: | |
1359 case LE: | |
1360 case LEU: | |
1361 case GT: | |
1362 case GTU: | |
1363 case GE: | |
1364 case GEU: | |
1365 return true; | |
1366 default: | |
1367 return false; | |
1368 } | |
1369 } | |
1370 | |
1322 /* Return 1 if this is a comparison operator. This allows the use of | 1371 /* Return 1 if this is a comparison operator. This allows the use of |
1323 MATCH_OPERATOR to recognize all the branch insns. */ | 1372 MATCH_OPERATOR to recognize all the branch insns. */ |
1324 | 1373 |
1325 int | 1374 int |
1326 comparison_operator (rtx op, enum machine_mode mode) | 1375 comparison_operator (rtx op, enum machine_mode mode) |
1327 { | 1376 { |
1328 return ((mode == VOIDmode || GET_MODE (op) == mode) | 1377 return ((mode == VOIDmode || GET_MODE (op) == mode) |
1329 && COMPARISON_P (op)); | 1378 && COMPARISON_P (op)); |
1330 } | 1379 } |
1331 | 1380 |
1381 /* If BODY is an insn body that uses ASM_OPERANDS, return it. */ | |
1382 | |
1383 rtx | |
1384 extract_asm_operands (rtx body) | |
1385 { | |
1386 rtx tmp; | |
1387 switch (GET_CODE (body)) | |
1388 { | |
1389 case ASM_OPERANDS: | |
1390 return body; | |
1391 | |
1392 case SET: | |
1393 /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */ | |
1394 tmp = SET_SRC (body); | |
1395 if (GET_CODE (tmp) == ASM_OPERANDS) | |
1396 return tmp; | |
1397 break; | |
1398 | |
1399 case PARALLEL: | |
1400 tmp = XVECEXP (body, 0, 0); | |
1401 if (GET_CODE (tmp) == ASM_OPERANDS) | |
1402 return tmp; | |
1403 if (GET_CODE (tmp) == SET) | |
1404 { | |
1405 tmp = SET_SRC (tmp); | |
1406 if (GET_CODE (tmp) == ASM_OPERANDS) | |
1407 return tmp; | |
1408 } | |
1409 break; | |
1410 | |
1411 default: | |
1412 break; | |
1413 } | |
1414 return NULL; | |
1415 } | |
1416 | |
1332 /* If BODY is an insn body that uses ASM_OPERANDS, | 1417 /* If BODY is an insn body that uses ASM_OPERANDS, |
1333 return the number of operands (both input and output) in the insn. | 1418 return the number of operands (both input and output) in the insn. |
1334 Otherwise return -1. */ | 1419 Otherwise return -1. */ |
1335 | 1420 |
1336 int | 1421 int |
1337 asm_noperands (const_rtx body) | 1422 asm_noperands (const_rtx body) |
1338 { | 1423 { |
1339 switch (GET_CODE (body)) | 1424 rtx asm_op = extract_asm_operands (CONST_CAST_RTX (body)); |
1340 { | 1425 int n_sets = 0; |
1341 case ASM_OPERANDS: | 1426 |
1342 /* No output operands: return number of input operands. */ | 1427 if (asm_op == NULL) |
1343 return ASM_OPERANDS_INPUT_LENGTH (body); | 1428 return -1; |
1344 case SET: | 1429 |
1345 if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS) | 1430 if (GET_CODE (body) == SET) |
1346 /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */ | 1431 n_sets = 1; |
1347 return ASM_OPERANDS_INPUT_LENGTH (SET_SRC (body)) + 1; | 1432 else if (GET_CODE (body) == PARALLEL) |
1348 else | 1433 { |
1349 return -1; | 1434 int i; |
1350 case PARALLEL: | 1435 if (GET_CODE (XVECEXP (body, 0, 0)) == SET) |
1351 if (GET_CODE (XVECEXP (body, 0, 0)) == SET | |
1352 && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) | |
1353 { | 1436 { |
1354 /* Multiple output operands, or 1 output plus some clobbers: | 1437 /* Multiple output operands, or 1 output plus some clobbers: |
1355 body is [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */ | 1438 body is |
1356 int i; | 1439 [(set OUTPUT (asm_operands ...))... (clobber (reg ...))...]. */ |
1357 int n_sets; | |
1358 | |
1359 /* Count backwards through CLOBBERs to determine number of SETs. */ | 1440 /* Count backwards through CLOBBERs to determine number of SETs. */ |
1360 for (i = XVECLEN (body, 0); i > 0; i--) | 1441 for (i = XVECLEN (body, 0); i > 0; i--) |
1361 { | 1442 { |
1362 if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET) | 1443 if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET) |
1363 break; | 1444 break; |
1379 if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS) | 1460 if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS) |
1380 return -1; | 1461 return -1; |
1381 /* If these ASM_OPERANDS rtx's came from different original insns | 1462 /* If these ASM_OPERANDS rtx's came from different original insns |
1382 then they aren't allowed together. */ | 1463 then they aren't allowed together. */ |
1383 if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt)) | 1464 if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt)) |
1384 != ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (body, 0, 0)))) | 1465 != ASM_OPERANDS_INPUT_VEC (asm_op)) |
1385 return -1; | 1466 return -1; |
1386 } | 1467 } |
1387 return (ASM_OPERANDS_INPUT_LENGTH (SET_SRC (XVECEXP (body, 0, 0))) | |
1388 + n_sets); | |
1389 } | 1468 } |
1390 else if (GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) | 1469 else |
1391 { | 1470 { |
1392 /* 0 outputs, but some clobbers: | 1471 /* 0 outputs, but some clobbers: |
1393 body is [(asm_operands ...) (clobber (reg ...))...]. */ | 1472 body is [(asm_operands ...) (clobber (reg ...))...]. */ |
1394 int i; | |
1395 | |
1396 /* Make sure all the other parallel things really are clobbers. */ | 1473 /* Make sure all the other parallel things really are clobbers. */ |
1397 for (i = XVECLEN (body, 0) - 1; i > 0; i--) | 1474 for (i = XVECLEN (body, 0) - 1; i > 0; i--) |
1398 if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER) | 1475 if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER) |
1399 return -1; | 1476 return -1; |
1400 | |
1401 return ASM_OPERANDS_INPUT_LENGTH (XVECEXP (body, 0, 0)); | |
1402 } | 1477 } |
1403 else | 1478 } |
1404 return -1; | 1479 |
1405 default: | 1480 return (ASM_OPERANDS_INPUT_LENGTH (asm_op) |
1406 return -1; | 1481 + ASM_OPERANDS_LABEL_LENGTH (asm_op) + n_sets); |
1407 } | |
1408 } | 1482 } |
1409 | 1483 |
1410 /* Assuming BODY is an insn body that uses ASM_OPERANDS, | 1484 /* Assuming BODY is an insn body that uses ASM_OPERANDS, |
1411 copy its operands (both input and output) into the vector OPERANDS, | 1485 copy its operands (both input and output) into the vector OPERANDS, |
1412 the locations of the operands within the insn into the vector OPERAND_LOCS, | 1486 the locations of the operands within the insn into the vector OPERAND_LOCS, |
1420 const char * | 1494 const char * |
1421 decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs, | 1495 decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs, |
1422 const char **constraints, enum machine_mode *modes, | 1496 const char **constraints, enum machine_mode *modes, |
1423 location_t *loc) | 1497 location_t *loc) |
1424 { | 1498 { |
1425 int i; | 1499 int nbase = 0, n, i; |
1426 int noperands; | 1500 rtx asmop; |
1427 rtx asmop = 0; | 1501 |
1428 | 1502 switch (GET_CODE (body)) |
1429 if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) == ASM_OPERANDS) | 1503 { |
1430 { | 1504 case ASM_OPERANDS: |
1505 /* Zero output asm: BODY is (asm_operands ...). */ | |
1506 asmop = body; | |
1507 break; | |
1508 | |
1509 case SET: | |
1510 /* Single output asm: BODY is (set OUTPUT (asm_operands ...)). */ | |
1431 asmop = SET_SRC (body); | 1511 asmop = SET_SRC (body); |
1432 /* Single output operand: BODY is (set OUTPUT (asm_operands ....)). */ | |
1433 | |
1434 noperands = ASM_OPERANDS_INPUT_LENGTH (asmop) + 1; | |
1435 | |
1436 for (i = 1; i < noperands; i++) | |
1437 { | |
1438 if (operand_locs) | |
1439 operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i - 1); | |
1440 if (operands) | |
1441 operands[i] = ASM_OPERANDS_INPUT (asmop, i - 1); | |
1442 if (constraints) | |
1443 constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i - 1); | |
1444 if (modes) | |
1445 modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i - 1); | |
1446 } | |
1447 | 1512 |
1448 /* The output is in the SET. | 1513 /* The output is in the SET. |
1449 Its constraint is in the ASM_OPERANDS itself. */ | 1514 Its constraint is in the ASM_OPERANDS itself. */ |
1450 if (operands) | 1515 if (operands) |
1451 operands[0] = SET_DEST (body); | 1516 operands[0] = SET_DEST (body); |
1453 operand_locs[0] = &SET_DEST (body); | 1518 operand_locs[0] = &SET_DEST (body); |
1454 if (constraints) | 1519 if (constraints) |
1455 constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop); | 1520 constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop); |
1456 if (modes) | 1521 if (modes) |
1457 modes[0] = GET_MODE (SET_DEST (body)); | 1522 modes[0] = GET_MODE (SET_DEST (body)); |
1458 } | 1523 nbase = 1; |
1459 else if (GET_CODE (body) == ASM_OPERANDS) | 1524 break; |
1460 { | 1525 |
1461 asmop = body; | 1526 case PARALLEL: |
1462 /* No output operands: BODY is (asm_operands ....). */ | 1527 { |
1463 | 1528 int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */ |
1464 noperands = ASM_OPERANDS_INPUT_LENGTH (asmop); | 1529 |
1465 | 1530 asmop = XVECEXP (body, 0, 0); |
1466 /* The input operands are found in the 1st element vector. */ | 1531 if (GET_CODE (asmop) == SET) |
1467 /* Constraints for inputs are in the 2nd element vector. */ | 1532 { |
1468 for (i = 0; i < noperands; i++) | 1533 asmop = SET_SRC (asmop); |
1469 { | 1534 |
1470 if (operand_locs) | 1535 /* At least one output, plus some CLOBBERs. The outputs are in |
1471 operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i); | 1536 the SETs. Their constraints are in the ASM_OPERANDS itself. */ |
1472 if (operands) | 1537 for (i = 0; i < nparallel; i++) |
1473 operands[i] = ASM_OPERANDS_INPUT (asmop, i); | 1538 { |
1474 if (constraints) | 1539 if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) |
1475 constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i); | 1540 break; /* Past last SET */ |
1476 if (modes) | 1541 if (operands) |
1477 modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i); | 1542 operands[i] = SET_DEST (XVECEXP (body, 0, i)); |
1478 } | 1543 if (operand_locs) |
1479 } | 1544 operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i)); |
1480 else if (GET_CODE (body) == PARALLEL | 1545 if (constraints) |
1481 && GET_CODE (XVECEXP (body, 0, 0)) == SET | 1546 constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1); |
1482 && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS) | 1547 if (modes) |
1483 { | 1548 modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i))); |
1484 int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */ | 1549 } |
1485 int nin; | 1550 nbase = i; |
1486 int nout = 0; /* Does not include CLOBBERs. */ | 1551 } |
1487 | 1552 break; |
1488 asmop = SET_SRC (XVECEXP (body, 0, 0)); | 1553 } |
1489 nin = ASM_OPERANDS_INPUT_LENGTH (asmop); | 1554 |
1490 | 1555 default: |
1491 /* At least one output, plus some CLOBBERs. */ | 1556 gcc_unreachable (); |
1492 | 1557 } |
1493 /* The outputs are in the SETs. | 1558 |
1494 Their constraints are in the ASM_OPERANDS itself. */ | 1559 n = ASM_OPERANDS_INPUT_LENGTH (asmop); |
1495 for (i = 0; i < nparallel; i++) | 1560 for (i = 0; i < n; i++) |
1496 { | 1561 { |
1497 if (GET_CODE (XVECEXP (body, 0, i)) == CLOBBER) | 1562 if (operand_locs) |
1498 break; /* Past last SET */ | 1563 operand_locs[nbase + i] = &ASM_OPERANDS_INPUT (asmop, i); |
1499 | 1564 if (operands) |
1500 if (operands) | 1565 operands[nbase + i] = ASM_OPERANDS_INPUT (asmop, i); |
1501 operands[i] = SET_DEST (XVECEXP (body, 0, i)); | 1566 if (constraints) |
1502 if (operand_locs) | 1567 constraints[nbase + i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i); |
1503 operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i)); | 1568 if (modes) |
1504 if (constraints) | 1569 modes[nbase + i] = ASM_OPERANDS_INPUT_MODE (asmop, i); |
1505 constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1); | 1570 } |
1506 if (modes) | 1571 nbase += n; |
1507 modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i))); | 1572 |
1508 nout++; | 1573 n = ASM_OPERANDS_LABEL_LENGTH (asmop); |
1509 } | 1574 for (i = 0; i < n; i++) |
1510 | 1575 { |
1511 for (i = 0; i < nin; i++) | 1576 if (operand_locs) |
1512 { | 1577 operand_locs[nbase + i] = &ASM_OPERANDS_LABEL (asmop, i); |
1513 if (operand_locs) | 1578 if (operands) |
1514 operand_locs[i + nout] = &ASM_OPERANDS_INPUT (asmop, i); | 1579 operands[nbase + i] = ASM_OPERANDS_LABEL (asmop, i); |
1515 if (operands) | 1580 if (constraints) |
1516 operands[i + nout] = ASM_OPERANDS_INPUT (asmop, i); | 1581 constraints[nbase + i] = ""; |
1517 if (constraints) | 1582 if (modes) |
1518 constraints[i + nout] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i); | 1583 modes[nbase + i] = Pmode; |
1519 if (modes) | |
1520 modes[i + nout] = ASM_OPERANDS_INPUT_MODE (asmop, i); | |
1521 } | |
1522 } | |
1523 else if (GET_CODE (body) == PARALLEL | |
1524 && GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS) | |
1525 { | |
1526 /* No outputs, but some CLOBBERs. */ | |
1527 | |
1528 int nin; | |
1529 | |
1530 asmop = XVECEXP (body, 0, 0); | |
1531 nin = ASM_OPERANDS_INPUT_LENGTH (asmop); | |
1532 | |
1533 for (i = 0; i < nin; i++) | |
1534 { | |
1535 if (operand_locs) | |
1536 operand_locs[i] = &ASM_OPERANDS_INPUT (asmop, i); | |
1537 if (operands) | |
1538 operands[i] = ASM_OPERANDS_INPUT (asmop, i); | |
1539 if (constraints) | |
1540 constraints[i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i); | |
1541 if (modes) | |
1542 modes[i] = ASM_OPERANDS_INPUT_MODE (asmop, i); | |
1543 } | |
1544 | |
1545 } | 1584 } |
1546 | 1585 |
1547 if (loc) | 1586 if (loc) |
1548 *loc = ASM_OPERANDS_SOURCE_LOCATION (asmop); | 1587 *loc = ASM_OPERANDS_SOURCE_LOCATION (asmop); |
1549 | 1588 |
1558 { | 1597 { |
1559 int result = 0; | 1598 int result = 0; |
1560 | 1599 |
1561 /* Use constrain_operands after reload. */ | 1600 /* Use constrain_operands after reload. */ |
1562 gcc_assert (!reload_completed); | 1601 gcc_assert (!reload_completed); |
1602 | |
1603 /* Empty constraint string is the same as "X,...,X", i.e. X for as | |
1604 many alternatives as required to match the other operands. */ | |
1605 if (*constraint == '\0') | |
1606 return 1; | |
1563 | 1607 |
1564 while (*constraint) | 1608 while (*constraint) |
1565 { | 1609 { |
1566 char c = *constraint; | 1610 char c = *constraint; |
1567 int len; | 1611 int len; |
1664 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint)) | 1708 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'H', constraint)) |
1665 result = 1; | 1709 result = 1; |
1666 break; | 1710 break; |
1667 | 1711 |
1668 case 's': | 1712 case 's': |
1669 if (GET_CODE (op) == CONST_INT | 1713 if (CONST_INT_P (op) |
1670 || (GET_CODE (op) == CONST_DOUBLE | 1714 || (GET_CODE (op) == CONST_DOUBLE |
1671 && GET_MODE (op) == VOIDmode)) | 1715 && GET_MODE (op) == VOIDmode)) |
1672 break; | 1716 break; |
1673 /* Fall through. */ | 1717 /* Fall through. */ |
1674 | 1718 |
1676 if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))) | 1720 if (CONSTANT_P (op) && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))) |
1677 result = 1; | 1721 result = 1; |
1678 break; | 1722 break; |
1679 | 1723 |
1680 case 'n': | 1724 case 'n': |
1681 if (GET_CODE (op) == CONST_INT | 1725 if (CONST_INT_P (op) |
1682 || (GET_CODE (op) == CONST_DOUBLE | 1726 || (GET_CODE (op) == CONST_DOUBLE |
1683 && GET_MODE (op) == VOIDmode)) | 1727 && GET_MODE (op) == VOIDmode)) |
1684 result = 1; | 1728 result = 1; |
1685 break; | 1729 break; |
1686 | 1730 |
1687 case 'I': | 1731 case 'I': |
1688 if (GET_CODE (op) == CONST_INT | 1732 if (CONST_INT_P (op) |
1689 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint)) | 1733 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'I', constraint)) |
1690 result = 1; | 1734 result = 1; |
1691 break; | 1735 break; |
1692 case 'J': | 1736 case 'J': |
1693 if (GET_CODE (op) == CONST_INT | 1737 if (CONST_INT_P (op) |
1694 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint)) | 1738 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'J', constraint)) |
1695 result = 1; | 1739 result = 1; |
1696 break; | 1740 break; |
1697 case 'K': | 1741 case 'K': |
1698 if (GET_CODE (op) == CONST_INT | 1742 if (CONST_INT_P (op) |
1699 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint)) | 1743 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', constraint)) |
1700 result = 1; | 1744 result = 1; |
1701 break; | 1745 break; |
1702 case 'L': | 1746 case 'L': |
1703 if (GET_CODE (op) == CONST_INT | 1747 if (CONST_INT_P (op) |
1704 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint)) | 1748 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'L', constraint)) |
1705 result = 1; | 1749 result = 1; |
1706 break; | 1750 break; |
1707 case 'M': | 1751 case 'M': |
1708 if (GET_CODE (op) == CONST_INT | 1752 if (CONST_INT_P (op) |
1709 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint)) | 1753 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'M', constraint)) |
1710 result = 1; | 1754 result = 1; |
1711 break; | 1755 break; |
1712 case 'N': | 1756 case 'N': |
1713 if (GET_CODE (op) == CONST_INT | 1757 if (CONST_INT_P (op) |
1714 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint)) | 1758 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'N', constraint)) |
1715 result = 1; | 1759 result = 1; |
1716 break; | 1760 break; |
1717 case 'O': | 1761 case 'O': |
1718 if (GET_CODE (op) == CONST_INT | 1762 if (CONST_INT_P (op) |
1719 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint)) | 1763 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'O', constraint)) |
1720 result = 1; | 1764 result = 1; |
1721 break; | 1765 break; |
1722 case 'P': | 1766 case 'P': |
1723 if (GET_CODE (op) == CONST_INT | 1767 if (CONST_INT_P (op) |
1724 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint)) | 1768 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'P', constraint)) |
1725 result = 1; | 1769 result = 1; |
1726 break; | 1770 break; |
1727 | 1771 |
1728 case 'X': | 1772 case 'X': |
1827 | 1871 |
1828 int | 1872 int |
1829 offsettable_memref_p (rtx op) | 1873 offsettable_memref_p (rtx op) |
1830 { | 1874 { |
1831 return ((MEM_P (op)) | 1875 return ((MEM_P (op)) |
1832 && offsettable_address_p (1, GET_MODE (op), XEXP (op, 0))); | 1876 && offsettable_address_addr_space_p (1, GET_MODE (op), XEXP (op, 0), |
1877 MEM_ADDR_SPACE (op))); | |
1833 } | 1878 } |
1834 | 1879 |
1835 /* Similar, but don't require a strictly valid mem ref: | 1880 /* Similar, but don't require a strictly valid mem ref: |
1836 consider pseudo-regs valid as index or base regs. */ | 1881 consider pseudo-regs valid as index or base regs. */ |
1837 | 1882 |
1838 int | 1883 int |
1839 offsettable_nonstrict_memref_p (rtx op) | 1884 offsettable_nonstrict_memref_p (rtx op) |
1840 { | 1885 { |
1841 return ((MEM_P (op)) | 1886 return ((MEM_P (op)) |
1842 && offsettable_address_p (0, GET_MODE (op), XEXP (op, 0))); | 1887 && offsettable_address_addr_space_p (0, GET_MODE (op), XEXP (op, 0), |
1888 MEM_ADDR_SPACE (op))); | |
1843 } | 1889 } |
1844 | 1890 |
1845 /* Return 1 if Y is a memory address which contains no side effects | 1891 /* Return 1 if Y is a memory address which contains no side effects |
1846 and would remain valid after the addition of a positive integer | 1892 and would remain valid for address space AS after the addition of |
1847 less than the size of that mode. | 1893 a positive integer less than the size of that mode. |
1848 | 1894 |
1849 We assume that the original address is valid and do not check it. | 1895 We assume that the original address is valid and do not check it. |
1850 We do check that it is valid for narrower modes. | 1896 We do check that it is valid for narrower modes. |
1851 | 1897 |
1852 If STRICTP is nonzero, we require a strictly valid address, | 1898 If STRICTP is nonzero, we require a strictly valid address, |
1853 for the sake of use in reload.c. */ | 1899 for the sake of use in reload.c. */ |
1854 | 1900 |
1855 int | 1901 int |
1856 offsettable_address_p (int strictp, enum machine_mode mode, rtx y) | 1902 offsettable_address_addr_space_p (int strictp, enum machine_mode mode, rtx y, |
1903 addr_space_t as) | |
1857 { | 1904 { |
1858 enum rtx_code ycode = GET_CODE (y); | 1905 enum rtx_code ycode = GET_CODE (y); |
1859 rtx z; | 1906 rtx z; |
1860 rtx y1 = y; | 1907 rtx y1 = y; |
1861 rtx *y2; | 1908 rtx *y2; |
1862 int (*addressp) (enum machine_mode, rtx) = | 1909 int (*addressp) (enum machine_mode, rtx, addr_space_t) = |
1863 (strictp ? strict_memory_address_p : memory_address_p); | 1910 (strictp ? strict_memory_address_addr_space_p |
1911 : memory_address_addr_space_p); | |
1864 unsigned int mode_sz = GET_MODE_SIZE (mode); | 1912 unsigned int mode_sz = GET_MODE_SIZE (mode); |
1865 | 1913 |
1866 if (CONSTANT_ADDRESS_P (y)) | 1914 if (CONSTANT_ADDRESS_P (y)) |
1867 return 1; | 1915 return 1; |
1868 | 1916 |
1888 | 1936 |
1889 y1 = *y2; | 1937 y1 = *y2; |
1890 *y2 = plus_constant (*y2, mode_sz - 1); | 1938 *y2 = plus_constant (*y2, mode_sz - 1); |
1891 /* Use QImode because an odd displacement may be automatically invalid | 1939 /* Use QImode because an odd displacement may be automatically invalid |
1892 for any wider mode. But it should be valid for a single byte. */ | 1940 for any wider mode. But it should be valid for a single byte. */ |
1893 good = (*addressp) (QImode, y); | 1941 good = (*addressp) (QImode, y, as); |
1894 | 1942 |
1895 /* In any case, restore old contents of memory. */ | 1943 /* In any case, restore old contents of memory. */ |
1896 *y2 = y1; | 1944 *y2 = y1; |
1897 return good; | 1945 return good; |
1898 } | 1946 } |
1913 else | 1961 else |
1914 z = plus_constant (y, mode_sz - 1); | 1962 z = plus_constant (y, mode_sz - 1); |
1915 | 1963 |
1916 /* Use QImode because an odd displacement may be automatically invalid | 1964 /* Use QImode because an odd displacement may be automatically invalid |
1917 for any wider mode. But it should be valid for a single byte. */ | 1965 for any wider mode. But it should be valid for a single byte. */ |
1918 return (*addressp) (QImode, z); | 1966 return (*addressp) (QImode, z, as); |
1919 } | 1967 } |
1920 | 1968 |
1921 /* Return 1 if ADDR is an address-expression whose effect depends | 1969 /* Return 1 if ADDR is an address-expression whose effect depends |
1922 on the mode of the memory reference it is used in. | 1970 on the mode of the memory reference it is used in. |
1923 | 1971 |
1996 case USE: | 2044 case USE: |
1997 case CLOBBER: | 2045 case CLOBBER: |
1998 case ASM_INPUT: | 2046 case ASM_INPUT: |
1999 case ADDR_VEC: | 2047 case ADDR_VEC: |
2000 case ADDR_DIFF_VEC: | 2048 case ADDR_DIFF_VEC: |
2049 case VAR_LOCATION: | |
2001 return; | 2050 return; |
2002 | 2051 |
2003 case SET: | 2052 case SET: |
2004 if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS) | 2053 if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS) |
2005 goto asm_insn; | 2054 goto asm_insn; |
2457 /* Memory operands must be valid, to the extent | 2506 /* Memory operands must be valid, to the extent |
2458 required by STRICT. */ | 2507 required by STRICT. */ |
2459 if (MEM_P (op)) | 2508 if (MEM_P (op)) |
2460 { | 2509 { |
2461 if (strict > 0 | 2510 if (strict > 0 |
2462 && !strict_memory_address_p (GET_MODE (op), | 2511 && !strict_memory_address_addr_space_p |
2463 XEXP (op, 0))) | 2512 (GET_MODE (op), XEXP (op, 0), |
2513 MEM_ADDR_SPACE (op))) | |
2464 break; | 2514 break; |
2465 if (strict == 0 | 2515 if (strict == 0 |
2466 && !memory_address_p (GET_MODE (op), XEXP (op, 0))) | 2516 && !memory_address_addr_space_p |
2517 (GET_MODE (op), XEXP (op, 0), | |
2518 MEM_ADDR_SPACE (op))) | |
2467 break; | 2519 break; |
2468 win = 1; | 2520 win = 1; |
2469 } | 2521 } |
2470 /* Before reload, accept what reload can turn into mem. */ | 2522 /* Before reload, accept what reload can turn into mem. */ |
2471 else if (strict < 0 && CONSTANT_P (op)) | 2523 else if (strict < 0 && CONSTANT_P (op)) |
2504 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p)) | 2556 && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p)) |
2505 win = 1; | 2557 win = 1; |
2506 break; | 2558 break; |
2507 | 2559 |
2508 case 's': | 2560 case 's': |
2509 if (GET_CODE (op) == CONST_INT | 2561 if (CONST_INT_P (op) |
2510 || (GET_CODE (op) == CONST_DOUBLE | 2562 || (GET_CODE (op) == CONST_DOUBLE |
2511 && GET_MODE (op) == VOIDmode)) | 2563 && GET_MODE (op) == VOIDmode)) |
2512 break; | 2564 break; |
2513 case 'i': | 2565 case 'i': |
2514 if (CONSTANT_P (op)) | 2566 if (CONSTANT_P (op)) |
2515 win = 1; | 2567 win = 1; |
2516 break; | 2568 break; |
2517 | 2569 |
2518 case 'n': | 2570 case 'n': |
2519 if (GET_CODE (op) == CONST_INT | 2571 if (CONST_INT_P (op) |
2520 || (GET_CODE (op) == CONST_DOUBLE | 2572 || (GET_CODE (op) == CONST_DOUBLE |
2521 && GET_MODE (op) == VOIDmode)) | 2573 && GET_MODE (op) == VOIDmode)) |
2522 win = 1; | 2574 win = 1; |
2523 break; | 2575 break; |
2524 | 2576 |
2528 case 'L': | 2580 case 'L': |
2529 case 'M': | 2581 case 'M': |
2530 case 'N': | 2582 case 'N': |
2531 case 'O': | 2583 case 'O': |
2532 case 'P': | 2584 case 'P': |
2533 if (GET_CODE (op) == CONST_INT | 2585 if (CONST_INT_P (op) |
2534 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p)) | 2586 && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p)) |
2535 win = 1; | 2587 win = 1; |
2536 break; | 2588 break; |
2537 | 2589 |
2538 case 'V': | 2590 case 'V': |
3024 | 3076 |
3025 search_ofs = 0; | 3077 search_ofs = 0; |
3026 return NULL_RTX; | 3078 return NULL_RTX; |
3027 } | 3079 } |
3028 | 3080 |
3081 /* Forget all currently tracked instructions, only remember current | |
3082 LIVE regset. */ | |
3083 | |
3084 static void | |
3085 peep2_reinit_state (regset live) | |
3086 { | |
3087 int i; | |
3088 | |
3089 /* Indicate that all slots except the last holds invalid data. */ | |
3090 for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i) | |
3091 peep2_insn_data[i].insn = NULL_RTX; | |
3092 peep2_current_count = 0; | |
3093 | |
3094 /* Indicate that the last slot contains live_after data. */ | |
3095 peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB; | |
3096 peep2_current = MAX_INSNS_PER_PEEP2; | |
3097 | |
3098 COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live); | |
3099 } | |
3100 | |
3029 /* Perform the peephole2 optimization pass. */ | 3101 /* Perform the peephole2 optimization pass. */ |
3030 | 3102 |
3031 static void | 3103 static void |
3032 peephole2_optimize (void) | 3104 peephole2_optimize (void) |
3033 { | 3105 { |
3047 live = BITMAP_ALLOC (®_obstack); | 3119 live = BITMAP_ALLOC (®_obstack); |
3048 | 3120 |
3049 FOR_EACH_BB_REVERSE (bb) | 3121 FOR_EACH_BB_REVERSE (bb) |
3050 { | 3122 { |
3051 rtl_profile_for_bb (bb); | 3123 rtl_profile_for_bb (bb); |
3052 /* Indicate that all slots except the last holds invalid data. */ | |
3053 for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i) | |
3054 peep2_insn_data[i].insn = NULL_RTX; | |
3055 peep2_current_count = 0; | |
3056 | |
3057 /* Indicate that the last slot contains live_after data. */ | |
3058 peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB; | |
3059 peep2_current = MAX_INSNS_PER_PEEP2; | |
3060 | 3124 |
3061 /* Start up propagation. */ | 3125 /* Start up propagation. */ |
3062 bitmap_copy (live, DF_LR_OUT (bb)); | 3126 bitmap_copy (live, DF_LR_OUT (bb)); |
3063 df_simulate_initialize_backwards (bb, live); | 3127 df_simulate_initialize_backwards (bb, live); |
3064 bitmap_copy (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live); | 3128 peep2_reinit_state (live); |
3065 | 3129 |
3066 for (insn = BB_END (bb); ; insn = prev) | 3130 for (insn = BB_END (bb); ; insn = prev) |
3067 { | 3131 { |
3068 prev = PREV_INSN (insn); | 3132 prev = PREV_INSN (insn); |
3069 if (INSN_P (insn)) | 3133 if (NONDEBUG_INSN_P (insn)) |
3070 { | 3134 { |
3071 rtx attempt, before_try, x; | 3135 rtx attempt, before_try, x; |
3072 int match_len; | 3136 int match_len; |
3073 rtx note; | 3137 rtx note; |
3074 bool was_call = false; | 3138 bool was_call = false; |
3086 if (RTX_FRAME_RELATED_P (insn)) | 3150 if (RTX_FRAME_RELATED_P (insn)) |
3087 { | 3151 { |
3088 /* If an insn has RTX_FRAME_RELATED_P set, peephole | 3152 /* If an insn has RTX_FRAME_RELATED_P set, peephole |
3089 substitution would lose the | 3153 substitution would lose the |
3090 REG_FRAME_RELATED_EXPR that is attached. */ | 3154 REG_FRAME_RELATED_EXPR that is attached. */ |
3091 peep2_current_count = 0; | 3155 peep2_reinit_state (live); |
3092 attempt = NULL; | 3156 attempt = NULL; |
3093 } | 3157 } |
3094 else | 3158 else |
3095 /* Match the peephole. */ | 3159 /* Match the peephole. */ |
3096 attempt = peephole2_insns (PATTERN (insn), insn, &match_len); | 3160 attempt = peephole2_insns (PATTERN (insn), insn, &match_len); |
3175 | 3239 |
3176 FOR_EACH_EDGE (eh_edge, ei, bb->succs) | 3240 FOR_EACH_EDGE (eh_edge, ei, bb->succs) |
3177 if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) | 3241 if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL)) |
3178 break; | 3242 break; |
3179 | 3243 |
3180 for (x = attempt ; x != before_try ; x = PREV_INSN (x)) | 3244 if (note) |
3181 if (CALL_P (x) | 3245 copy_reg_eh_region_note_backward (note, attempt, |
3182 || (flag_non_call_exceptions | 3246 before_try); |
3183 && may_trap_p (PATTERN (x)) | 3247 |
3184 && !find_reg_note (x, REG_EH_REGION, NULL))) | 3248 if (eh_edge) |
3185 { | 3249 for (x = attempt ; x != before_try ; x = PREV_INSN (x)) |
3186 if (note) | 3250 if (x != BB_END (bb) |
3187 add_reg_note (x, REG_EH_REGION, XEXP (note, 0)); | 3251 && (can_throw_internal (x) |
3188 | 3252 || can_nonlocal_goto (x))) |
3189 if (x != BB_END (bb) && eh_edge) | 3253 { |
3190 { | 3254 edge nfte, nehe; |
3191 edge nfte, nehe; | 3255 int flags; |
3192 int flags; | 3256 |
3193 | 3257 nfte = split_block (bb, x); |
3194 nfte = split_block (bb, x); | 3258 flags = (eh_edge->flags |
3195 flags = (eh_edge->flags | 3259 & (EDGE_EH | EDGE_ABNORMAL)); |
3196 & (EDGE_EH | EDGE_ABNORMAL)); | 3260 if (CALL_P (x)) |
3197 if (CALL_P (x)) | 3261 flags |= EDGE_ABNORMAL_CALL; |
3198 flags |= EDGE_ABNORMAL_CALL; | 3262 nehe = make_edge (nfte->src, eh_edge->dest, |
3199 nehe = make_edge (nfte->src, eh_edge->dest, | 3263 flags); |
3200 flags); | 3264 |
3201 | 3265 nehe->probability = eh_edge->probability; |
3202 nehe->probability = eh_edge->probability; | 3266 nfte->probability |
3203 nfte->probability | 3267 = REG_BR_PROB_BASE - nehe->probability; |
3204 = REG_BR_PROB_BASE - nehe->probability; | 3268 |
3205 | 3269 do_cleanup_cfg |= purge_dead_edges (nfte->dest); |
3206 do_cleanup_cfg |= purge_dead_edges (nfte->dest); | 3270 bb = nfte->src; |
3207 bb = nfte->src; | 3271 eh_edge = nehe; |
3208 eh_edge = nehe; | 3272 } |
3209 } | |
3210 } | |
3211 | 3273 |
3212 /* Converting possibly trapping insn to non-trapping is | 3274 /* Converting possibly trapping insn to non-trapping is |
3213 possible. Zap dummy outgoing edges. */ | 3275 possible. Zap dummy outgoing edges. */ |
3214 do_cleanup_cfg |= purge_dead_edges (bb); | 3276 do_cleanup_cfg |= purge_dead_edges (bb); |
3215 } | 3277 } |
3216 | 3278 |
3217 #ifdef HAVE_conditional_execution | 3279 if (targetm.have_conditional_execution ()) |
3218 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) | |
3219 peep2_insn_data[i].insn = NULL_RTX; | |
3220 peep2_insn_data[peep2_current].insn = PEEP2_EOB; | |
3221 peep2_current_count = 0; | |
3222 #else | |
3223 /* Back up lifetime information past the end of the | |
3224 newly created sequence. */ | |
3225 if (++i >= MAX_INSNS_PER_PEEP2 + 1) | |
3226 i = 0; | |
3227 bitmap_copy (live, peep2_insn_data[i].live_before); | |
3228 | |
3229 /* Update life information for the new sequence. */ | |
3230 x = attempt; | |
3231 do | |
3232 { | 3280 { |
3233 if (INSN_P (x)) | 3281 for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) |
3282 peep2_insn_data[i].insn = NULL_RTX; | |
3283 peep2_insn_data[peep2_current].insn = PEEP2_EOB; | |
3284 peep2_current_count = 0; | |
3285 } | |
3286 else | |
3287 { | |
3288 /* Back up lifetime information past the end of the | |
3289 newly created sequence. */ | |
3290 if (++i >= MAX_INSNS_PER_PEEP2 + 1) | |
3291 i = 0; | |
3292 bitmap_copy (live, peep2_insn_data[i].live_before); | |
3293 | |
3294 /* Update life information for the new sequence. */ | |
3295 x = attempt; | |
3296 do | |
3234 { | 3297 { |
3235 if (--i < 0) | 3298 if (INSN_P (x)) |
3236 i = MAX_INSNS_PER_PEEP2; | 3299 { |
3237 if (peep2_current_count < MAX_INSNS_PER_PEEP2 | 3300 if (--i < 0) |
3238 && peep2_insn_data[i].insn == NULL_RTX) | 3301 i = MAX_INSNS_PER_PEEP2; |
3239 peep2_current_count++; | 3302 if (peep2_current_count < MAX_INSNS_PER_PEEP2 |
3240 peep2_insn_data[i].insn = x; | 3303 && peep2_insn_data[i].insn == NULL_RTX) |
3241 df_insn_rescan (x); | 3304 peep2_current_count++; |
3242 df_simulate_one_insn_backwards (bb, x, live); | 3305 peep2_insn_data[i].insn = x; |
3243 bitmap_copy (peep2_insn_data[i].live_before, live); | 3306 df_insn_rescan (x); |
3307 df_simulate_one_insn_backwards (bb, x, live); | |
3308 bitmap_copy (peep2_insn_data[i].live_before, | |
3309 live); | |
3310 } | |
3311 x = PREV_INSN (x); | |
3244 } | 3312 } |
3245 x = PREV_INSN (x); | 3313 while (x != prev); |
3314 | |
3315 peep2_current = i; | |
3246 } | 3316 } |
3247 while (x != prev); | |
3248 | |
3249 peep2_current = i; | |
3250 #endif | |
3251 | 3317 |
3252 /* If we generated a jump instruction, it won't have | 3318 /* If we generated a jump instruction, it won't have |
3253 JUMP_LABEL set. Recompute after we're done. */ | 3319 JUMP_LABEL set. Recompute after we're done. */ |
3254 for (x = attempt; x != before_try; x = PREV_INSN (x)) | 3320 for (x = attempt; x != before_try; x = PREV_INSN (x)) |
3255 if (JUMP_P (x)) | 3321 if (JUMP_P (x)) |
3472 NULL, /* gate */ | 3538 NULL, /* gate */ |
3473 rest_of_handle_split_all_insns, /* execute */ | 3539 rest_of_handle_split_all_insns, /* execute */ |
3474 NULL, /* sub */ | 3540 NULL, /* sub */ |
3475 NULL, /* next */ | 3541 NULL, /* next */ |
3476 0, /* static_pass_number */ | 3542 0, /* static_pass_number */ |
3477 0, /* tv_id */ | 3543 TV_NONE, /* tv_id */ |
3478 0, /* properties_required */ | 3544 0, /* properties_required */ |
3479 0, /* properties_provided */ | 3545 0, /* properties_provided */ |
3480 0, /* properties_destroyed */ | 3546 0, /* properties_destroyed */ |
3481 0, /* todo_flags_start */ | 3547 0, /* todo_flags_start */ |
3482 TODO_dump_func /* todo_flags_finish */ | 3548 TODO_dump_func /* todo_flags_finish */ |
3502 NULL, /* gate */ | 3568 NULL, /* gate */ |
3503 rest_of_handle_split_after_reload, /* execute */ | 3569 rest_of_handle_split_after_reload, /* execute */ |
3504 NULL, /* sub */ | 3570 NULL, /* sub */ |
3505 NULL, /* next */ | 3571 NULL, /* next */ |
3506 0, /* static_pass_number */ | 3572 0, /* static_pass_number */ |
3507 0, /* tv_id */ | 3573 TV_NONE, /* tv_id */ |
3508 0, /* properties_required */ | 3574 0, /* properties_required */ |
3509 0, /* properties_provided */ | 3575 0, /* properties_provided */ |
3510 0, /* properties_destroyed */ | 3576 0, /* properties_destroyed */ |
3511 0, /* todo_flags_start */ | 3577 0, /* todo_flags_start */ |
3512 TODO_dump_func /* todo_flags_finish */ | 3578 TODO_dump_func /* todo_flags_finish */ |
3546 gate_handle_split_before_regstack, /* gate */ | 3612 gate_handle_split_before_regstack, /* gate */ |
3547 rest_of_handle_split_before_regstack, /* execute */ | 3613 rest_of_handle_split_before_regstack, /* execute */ |
3548 NULL, /* sub */ | 3614 NULL, /* sub */ |
3549 NULL, /* next */ | 3615 NULL, /* next */ |
3550 0, /* static_pass_number */ | 3616 0, /* static_pass_number */ |
3551 0, /* tv_id */ | 3617 TV_NONE, /* tv_id */ |
3552 0, /* properties_required */ | 3618 0, /* properties_required */ |
3553 0, /* properties_provided */ | 3619 0, /* properties_provided */ |
3554 0, /* properties_destroyed */ | 3620 0, /* properties_destroyed */ |
3555 0, /* todo_flags_start */ | 3621 0, /* todo_flags_start */ |
3556 TODO_dump_func /* todo_flags_finish */ | 3622 TODO_dump_func /* todo_flags_finish */ |
3584 gate_handle_split_before_sched2, /* gate */ | 3650 gate_handle_split_before_sched2, /* gate */ |
3585 rest_of_handle_split_before_sched2, /* execute */ | 3651 rest_of_handle_split_before_sched2, /* execute */ |
3586 NULL, /* sub */ | 3652 NULL, /* sub */ |
3587 NULL, /* next */ | 3653 NULL, /* next */ |
3588 0, /* static_pass_number */ | 3654 0, /* static_pass_number */ |
3589 0, /* tv_id */ | 3655 TV_NONE, /* tv_id */ |
3590 0, /* properties_required */ | 3656 0, /* properties_required */ |
3591 0, /* properties_provided */ | 3657 0, /* properties_provided */ |
3592 0, /* properties_destroyed */ | 3658 0, /* properties_destroyed */ |
3593 0, /* todo_flags_start */ | 3659 0, /* todo_flags_start */ |
3594 TODO_verify_flow | | 3660 TODO_verify_flow | |
3603 { | 3669 { |
3604 #if defined (HAVE_ATTR_length) && !defined (STACK_REGS) | 3670 #if defined (HAVE_ATTR_length) && !defined (STACK_REGS) |
3605 return 1; | 3671 return 1; |
3606 #else | 3672 #else |
3607 return 0; | 3673 return 0; |
3608 #endif | 3674 #endif |
3609 } | 3675 } |
3610 | 3676 |
3611 struct rtl_opt_pass pass_split_for_shorten_branches = | 3677 struct rtl_opt_pass pass_split_for_shorten_branches = |
3612 { | 3678 { |
3613 { | 3679 { |
3616 gate_do_final_split, /* gate */ | 3682 gate_do_final_split, /* gate */ |
3617 split_all_insns_noflow, /* execute */ | 3683 split_all_insns_noflow, /* execute */ |
3618 NULL, /* sub */ | 3684 NULL, /* sub */ |
3619 NULL, /* next */ | 3685 NULL, /* next */ |
3620 0, /* static_pass_number */ | 3686 0, /* static_pass_number */ |
3621 0, /* tv_id */ | 3687 TV_NONE, /* tv_id */ |
3622 0, /* properties_required */ | 3688 0, /* properties_required */ |
3623 0, /* properties_provided */ | 3689 0, /* properties_provided */ |
3624 0, /* properties_destroyed */ | 3690 0, /* properties_destroyed */ |
3625 0, /* todo_flags_start */ | 3691 0, /* todo_flags_start */ |
3626 TODO_dump_func | TODO_verify_rtl_sharing /* todo_flags_finish */ | 3692 TODO_dump_func | TODO_verify_rtl_sharing /* todo_flags_finish */ |
3627 } | 3693 } |
3628 }; | 3694 }; |
3629 | |
3630 |