Mercurial > hg > CbC > CbC_gcc
comparison gcc/sel-sched.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Instruction scheduling pass. Selective scheduler and pipeliner. | 1 /* Instruction scheduling pass. Selective scheduler and pipeliner. |
2 Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 | 2 Copyright (C) 2006-2017 Free Software Foundation, Inc. |
3 Free Software Foundation, Inc. | |
4 | 3 |
5 This file is part of GCC. | 4 This file is part of GCC. |
6 | 5 |
7 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 |
8 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 |
19 <http://www.gnu.org/licenses/>. */ | 18 <http://www.gnu.org/licenses/>. */ |
20 | 19 |
21 #include "config.h" | 20 #include "config.h" |
22 #include "system.h" | 21 #include "system.h" |
23 #include "coretypes.h" | 22 #include "coretypes.h" |
24 #include "tm.h" | 23 #include "backend.h" |
25 #include "rtl-error.h" | 24 #include "tree.h" |
25 #include "rtl.h" | |
26 #include "df.h" | |
27 #include "memmodel.h" | |
26 #include "tm_p.h" | 28 #include "tm_p.h" |
27 #include "hard-reg-set.h" | |
28 #include "regs.h" | 29 #include "regs.h" |
29 #include "function.h" | 30 #include "cfgbuild.h" |
30 #include "flags.h" | |
31 #include "insn-config.h" | 31 #include "insn-config.h" |
32 #include "insn-attr.h" | 32 #include "insn-attr.h" |
33 #include "except.h" | |
34 #include "recog.h" | |
35 #include "params.h" | 33 #include "params.h" |
36 #include "target.h" | 34 #include "target.h" |
37 #include "output.h" | |
38 #include "timevar.h" | |
39 #include "tree-pass.h" | |
40 #include "sched-int.h" | 35 #include "sched-int.h" |
41 #include "ggc.h" | |
42 #include "tree.h" | |
43 #include "vec.h" | |
44 #include "langhooks.h" | |
45 #include "rtlhooks-def.h" | 36 #include "rtlhooks-def.h" |
46 #include "output.h" | 37 #include "ira.h" |
47 #include "emit-rtl.h" | 38 #include "ira-int.h" |
39 #include "rtl-iter.h" | |
48 | 40 |
49 #ifdef INSN_SCHEDULING | 41 #ifdef INSN_SCHEDULING |
42 #include "regset.h" | |
43 #include "cfgloop.h" | |
50 #include "sel-sched-ir.h" | 44 #include "sel-sched-ir.h" |
51 #include "sel-sched-dump.h" | 45 #include "sel-sched-dump.h" |
52 #include "sel-sched.h" | 46 #include "sel-sched.h" |
53 #include "dbgcnt.h" | 47 #include "dbgcnt.h" |
54 | 48 |
283 struct rtx_search_arg | 277 struct rtx_search_arg |
284 { | 278 { |
285 /* What we are searching for. */ | 279 /* What we are searching for. */ |
286 rtx x; | 280 rtx x; |
287 | 281 |
288 /* The occurence counter. */ | 282 /* The occurrence counter. */ |
289 int n; | 283 int n; |
290 }; | 284 }; |
291 | 285 |
292 typedef struct rtx_search_arg *rtx_search_arg_p; | 286 typedef struct rtx_search_arg *rtx_search_arg_p; |
293 | 287 |
377 | 371 |
378 /* An UID of expr_vliw which is to be moved up. If we find other exprs, | 372 /* An UID of expr_vliw which is to be moved up. If we find other exprs, |
379 they are to be removed. */ | 373 they are to be removed. */ |
380 int uid; | 374 int uid; |
381 | 375 |
382 #ifdef ENABLE_CHECKING | |
383 /* This is initialized to the insn on which the driver stopped its traversal. */ | 376 /* This is initialized to the insn on which the driver stopped its traversal. */ |
384 insn_t failed_insn; | 377 insn_t failed_insn; |
385 #endif | |
386 | 378 |
387 /* True if we scheduled an insn with different register. */ | 379 /* True if we scheduled an insn with different register. */ |
388 bool was_renamed; | 380 bool was_renamed; |
389 }; | 381 }; |
390 | 382 |
403 | 395 |
404 typedef struct fur_static_params *fur_static_params_p; | 396 typedef struct fur_static_params *fur_static_params_p; |
405 typedef struct cmpd_local_params *cmpd_local_params_p; | 397 typedef struct cmpd_local_params *cmpd_local_params_p; |
406 typedef struct moveop_static_params *moveop_static_params_p; | 398 typedef struct moveop_static_params *moveop_static_params_p; |
407 | 399 |
408 /* Set of hooks and parameters that determine behaviour specific to | 400 /* Set of hooks and parameters that determine behavior specific to |
409 move_op or find_used_regs functions. */ | 401 move_op or find_used_regs functions. */ |
410 struct code_motion_path_driver_info_def | 402 struct code_motion_path_driver_info_def |
411 { | 403 { |
412 /* Called on enter to the basic block. */ | 404 /* Called on enter to the basic block. */ |
413 int (*on_enter) (insn_t, cmpd_local_params_p, void *, bool); | 405 int (*on_enter) (insn_t, cmpd_local_params_p, void *, bool); |
501 | 493 |
502 /* Number of insns scheduled in current region. */ | 494 /* Number of insns scheduled in current region. */ |
503 static int num_insns_scheduled; | 495 static int num_insns_scheduled; |
504 | 496 |
505 /* A vector of expressions is used to be able to sort them. */ | 497 /* A vector of expressions is used to be able to sort them. */ |
506 DEF_VEC_P(expr_t); | 498 static vec<expr_t> vec_av_set; |
507 DEF_VEC_ALLOC_P(expr_t,heap); | |
508 static VEC(expr_t, heap) *vec_av_set = NULL; | |
509 | 499 |
510 /* A vector of vinsns is used to hold temporary lists of vinsns. */ | 500 /* A vector of vinsns is used to hold temporary lists of vinsns. */ |
511 DEF_VEC_P(vinsn_t); | 501 typedef vec<vinsn_t> vinsn_vec_t; |
512 DEF_VEC_ALLOC_P(vinsn_t,heap); | |
513 typedef VEC(vinsn_t, heap) *vinsn_vec_t; | |
514 | 502 |
515 /* This vector has the exprs which may still present in av_sets, but actually | 503 /* This vector has the exprs which may still present in av_sets, but actually |
516 can't be moved up due to bookkeeping created during code motion to another | 504 can't be moved up due to bookkeeping created during code motion to another |
517 fence. See comment near the call to update_and_record_unavailable_insns | 505 fence. See comment near the call to update_and_record_unavailable_insns |
518 for the detailed explanations. */ | 506 for the detailed explanations. */ |
519 static vinsn_vec_t vec_bookkeeping_blocked_vinsns = NULL; | 507 static vinsn_vec_t vec_bookkeeping_blocked_vinsns = vinsn_vec_t (); |
520 | 508 |
521 /* This vector has vinsns which are scheduled with renaming on the first fence | 509 /* This vector has vinsns which are scheduled with renaming on the first fence |
522 and then seen on the second. For expressions with such vinsns, target | 510 and then seen on the second. For expressions with such vinsns, target |
523 availability information may be wrong. */ | 511 availability information may be wrong. */ |
524 static vinsn_vec_t vec_target_unavailable_vinsns = NULL; | 512 static vinsn_vec_t vec_target_unavailable_vinsns = vinsn_vec_t (); |
525 | 513 |
526 /* Vector to store temporary nops inserted in move_op to prevent removal | 514 /* Vector to store temporary nops inserted in move_op to prevent removal |
527 of empty bbs. */ | 515 of empty bbs. */ |
528 DEF_VEC_P(insn_t); | 516 static vec<insn_t> vec_temp_moveop_nops; |
529 DEF_VEC_ALLOC_P(insn_t,heap); | |
530 static VEC(insn_t, heap) *vec_temp_moveop_nops = NULL; | |
531 | 517 |
532 /* These bitmaps record original instructions scheduled on the current | 518 /* These bitmaps record original instructions scheduled on the current |
533 iteration and bookkeeping copies created by them. */ | 519 iteration and bookkeeping copies created by them. */ |
534 static bitmap current_originators = NULL; | 520 static bitmap current_originators = NULL; |
535 static bitmap current_copies = NULL; | 521 static bitmap current_copies = NULL; |
579 static void | 565 static void |
580 advance_one_cycle (fence_t fence) | 566 advance_one_cycle (fence_t fence) |
581 { | 567 { |
582 unsigned i; | 568 unsigned i; |
583 int cycle; | 569 int cycle; |
584 rtx insn; | 570 rtx_insn *insn; |
585 | 571 |
586 advance_state (FENCE_STATE (fence)); | 572 advance_state (FENCE_STATE (fence)); |
587 cycle = ++FENCE_CYCLE (fence); | 573 cycle = ++FENCE_CYCLE (fence); |
588 FENCE_ISSUED_INSNS (fence) = 0; | 574 FENCE_ISSUED_INSNS (fence) = 0; |
589 FENCE_STARTS_CYCLE_P (fence) = 1; | 575 FENCE_STARTS_CYCLE_P (fence) = 1; |
590 can_issue_more = issue_rate; | 576 can_issue_more = issue_rate; |
591 FENCE_ISSUE_MORE (fence) = can_issue_more; | 577 FENCE_ISSUE_MORE (fence) = can_issue_more; |
592 | 578 |
593 for (i = 0; VEC_iterate (rtx, FENCE_EXECUTING_INSNS (fence), i, insn); ) | 579 for (i = 0; vec_safe_iterate (FENCE_EXECUTING_INSNS (fence), i, &insn); ) |
594 { | 580 { |
595 if (INSN_READY_CYCLE (insn) < cycle) | 581 if (INSN_READY_CYCLE (insn) < cycle) |
596 { | 582 { |
597 remove_from_deps (FENCE_DC (fence), insn); | 583 remove_from_deps (FENCE_DC (fence), insn); |
598 VEC_unordered_remove (rtx, FENCE_EXECUTING_INSNS (fence), i); | 584 FENCE_EXECUTING_INSNS (fence)->unordered_remove (i); |
599 continue; | 585 continue; |
600 } | 586 } |
601 i++; | 587 i++; |
602 } | 588 } |
603 if (sched_verbose >= 2) | 589 if (sched_verbose >= 2) |
608 } | 594 } |
609 | 595 |
610 /* Returns true when SUCC in a fallthru bb of INSN, possibly | 596 /* Returns true when SUCC in a fallthru bb of INSN, possibly |
611 skipping empty basic blocks. */ | 597 skipping empty basic blocks. */ |
612 static bool | 598 static bool |
613 in_fallthru_bb_p (rtx insn, rtx succ) | 599 in_fallthru_bb_p (rtx_insn *insn, rtx succ) |
614 { | 600 { |
615 basic_block bb = BLOCK_FOR_INSN (insn); | 601 basic_block bb = BLOCK_FOR_INSN (insn); |
616 edge e; | 602 edge e; |
617 | 603 |
618 if (bb == BLOCK_FOR_INSN (succ)) | 604 if (bb == BLOCK_FOR_INSN (succ)) |
637 static void | 623 static void |
638 extract_new_fences_from (flist_t old_fences, flist_tail_t new_fences, | 624 extract_new_fences_from (flist_t old_fences, flist_tail_t new_fences, |
639 int orig_max_seqno) | 625 int orig_max_seqno) |
640 { | 626 { |
641 bool was_here_p = false; | 627 bool was_here_p = false; |
642 insn_t insn = NULL_RTX; | 628 insn_t insn = NULL; |
643 insn_t succ; | 629 insn_t succ; |
644 succ_iterator si; | 630 succ_iterator si; |
645 ilist_iterator ii; | 631 ilist_iterator ii; |
646 fence_t fence = FLIST_FENCE (old_fences); | 632 fence_t fence = FLIST_FENCE (old_fences); |
647 basic_block bb; | 633 basic_block bb; |
731 && REG_P (INSN_RHS (insn))) | 717 && REG_P (INSN_RHS (insn))) |
732 return true; | 718 return true; |
733 return false; | 719 return false; |
734 } | 720 } |
735 | 721 |
736 /* Substitute all occurences of INSN's destination in EXPR' vinsn with INSN's | 722 /* Substitute all occurrences of INSN's destination in EXPR' vinsn with INSN's |
737 source (if INSN is eligible for substitution). Returns TRUE if | 723 source (if INSN is eligible for substitution). Returns TRUE if |
738 substitution was actually performed, FALSE otherwise. Substitution might | 724 substitution was actually performed, FALSE otherwise. Substitution might |
739 be not performed because it's either EXPR' vinsn doesn't contain INSN's | 725 be not performed because it's either EXPR' vinsn doesn't contain INSN's |
740 destination or the resulting insn is invalid for the target machine. | 726 destination or the resulting insn is invalid for the target machine. |
741 When UNDO is true, perform unsubstitution instead (the difference is in | 727 When UNDO is true, perform unsubstitution instead (the difference is in |
760 old = undo ? INSN_RHS (insn) : INSN_LHS (insn); | 746 old = undo ? INSN_RHS (insn) : INSN_LHS (insn); |
761 | 747 |
762 /* Substitute if INSN has a form of x:=y and LHS(INSN) occurs in *VI. */ | 748 /* Substitute if INSN has a form of x:=y and LHS(INSN) occurs in *VI. */ |
763 if (rtx_ok_for_substitution_p (old, *where)) | 749 if (rtx_ok_for_substitution_p (old, *where)) |
764 { | 750 { |
765 rtx new_insn; | 751 rtx_insn *new_insn; |
766 rtx *where_replace; | 752 rtx *where_replace; |
767 | 753 |
768 /* We should copy these rtxes before substitution. */ | 754 /* We should copy these rtxes before substitution. */ |
769 new_rtx = copy_rtx (undo ? INSN_LHS (insn) : INSN_RHS (insn)); | 755 new_rtx = copy_rtx (undo ? INSN_LHS (insn) : INSN_RHS (insn)); |
770 new_insn = create_copy_of_insn_rtx (VINSN_INSN_RTX (*vi)); | 756 new_insn = create_copy_of_insn_rtx (VINSN_INSN_RTX (*vi)); |
792 create_vinsn_from_insn_rtx (new_insn, false)); | 778 create_vinsn_from_insn_rtx (new_insn, false)); |
793 | 779 |
794 /* Do not allow clobbering the address register of speculative | 780 /* Do not allow clobbering the address register of speculative |
795 insns. */ | 781 insns. */ |
796 if ((EXPR_SPEC_DONE_DS (expr) & SPECULATIVE) | 782 if ((EXPR_SPEC_DONE_DS (expr) & SPECULATIVE) |
797 && bitmap_bit_p (VINSN_REG_USES (EXPR_VINSN (expr)), | 783 && register_unavailable_p (VINSN_REG_USES (EXPR_VINSN (expr)), |
798 expr_dest_regno (expr))) | 784 expr_dest_reg (expr))) |
799 EXPR_TARGET_AVAILABLE (expr) = false; | 785 EXPR_TARGET_AVAILABLE (expr) = false; |
800 | 786 |
801 return true; | 787 return true; |
802 } | 788 } |
803 else | 789 else |
805 } | 791 } |
806 else | 792 else |
807 return false; | 793 return false; |
808 } | 794 } |
809 | 795 |
810 /* Helper function for count_occurences_equiv. */ | |
811 static int | |
812 count_occurrences_1 (rtx *cur_rtx, void *arg) | |
813 { | |
814 rtx_search_arg_p p = (rtx_search_arg_p) arg; | |
815 | |
816 /* The last param FOR_GCSE is true, because otherwise it performs excessive | |
817 substitutions like | |
818 r8 = r33 | |
819 r16 = r33 | |
820 for the last insn it presumes r33 equivalent to r8, so it changes it to | |
821 r33. Actually, there's no change, but it spoils debugging. */ | |
822 if (exp_equiv_p (*cur_rtx, p->x, 0, true)) | |
823 { | |
824 /* Bail out if we occupy more than one register. */ | |
825 if (REG_P (*cur_rtx) | |
826 && HARD_REGISTER_P (*cur_rtx) | |
827 && hard_regno_nregs[REGNO(*cur_rtx)][GET_MODE (*cur_rtx)] > 1) | |
828 { | |
829 p->n = 0; | |
830 return 1; | |
831 } | |
832 | |
833 p->n++; | |
834 | |
835 /* Do not traverse subexprs. */ | |
836 return -1; | |
837 } | |
838 | |
839 if (GET_CODE (*cur_rtx) == SUBREG | |
840 && REG_P (p->x) | |
841 && (!REG_P (SUBREG_REG (*cur_rtx)) | |
842 || REGNO (SUBREG_REG (*cur_rtx)) == REGNO (p->x))) | |
843 { | |
844 /* ??? Do not support substituting regs inside subregs. In that case, | |
845 simplify_subreg will be called by validate_replace_rtx, and | |
846 unsubstitution will fail later. */ | |
847 p->n = 0; | |
848 return 1; | |
849 } | |
850 | |
851 /* Continue search. */ | |
852 return 0; | |
853 } | |
854 | |
855 /* Return the number of places WHAT appears within WHERE. | 796 /* Return the number of places WHAT appears within WHERE. |
856 Bail out when we found a reference occupying several hard registers. */ | 797 Bail out when we found a reference occupying several hard registers. */ |
857 static int | 798 static int |
858 count_occurrences_equiv (rtx what, rtx where) | 799 count_occurrences_equiv (const_rtx what, const_rtx where) |
859 { | 800 { |
860 struct rtx_search_arg arg; | 801 int count = 0; |
861 | 802 subrtx_iterator::array_type array; |
862 arg.x = what; | 803 FOR_EACH_SUBRTX (iter, array, where, NONCONST) |
863 arg.n = 0; | 804 { |
864 | 805 const_rtx x = *iter; |
865 for_each_rtx (&where, &count_occurrences_1, (void *) &arg); | 806 if (REG_P (x) && REGNO (x) == REGNO (what)) |
866 | 807 { |
867 return arg.n; | 808 /* Bail out if mode is different or more than one register is |
809 used. */ | |
810 if (GET_MODE (x) != GET_MODE (what) || REG_NREGS (x) > 1) | |
811 return 0; | |
812 count += 1; | |
813 } | |
814 else if (GET_CODE (x) == SUBREG | |
815 && (!REG_P (SUBREG_REG (x)) | |
816 || REGNO (SUBREG_REG (x)) == REGNO (what))) | |
817 /* ??? Do not support substituting regs inside subregs. In that case, | |
818 simplify_subreg will be called by validate_replace_rtx, and | |
819 unsubstitution will fail later. */ | |
820 return 0; | |
821 } | |
822 return count; | |
868 } | 823 } |
869 | 824 |
870 /* Returns TRUE if WHAT is found in WHERE rtx tree. */ | 825 /* Returns TRUE if WHAT is found in WHERE rtx tree. */ |
871 static bool | 826 static bool |
872 rtx_ok_for_substitution_p (rtx what, rtx where) | 827 rtx_ok_for_substitution_p (rtx what, rtx where) |
877 | 832 |
878 /* Functions to support register renaming. */ | 833 /* Functions to support register renaming. */ |
879 | 834 |
880 /* Substitute VI's set source with REGNO. Returns newly created pattern | 835 /* Substitute VI's set source with REGNO. Returns newly created pattern |
881 that has REGNO as its source. */ | 836 that has REGNO as its source. */ |
882 static rtx | 837 static rtx_insn * |
883 create_insn_rtx_with_rhs (vinsn_t vi, rtx rhs_rtx) | 838 create_insn_rtx_with_rhs (vinsn_t vi, rtx rhs_rtx) |
884 { | 839 { |
885 rtx lhs_rtx; | 840 rtx lhs_rtx; |
886 rtx pattern; | 841 rtx pattern; |
887 rtx insn_rtx; | 842 rtx_insn *insn_rtx; |
888 | 843 |
889 lhs_rtx = copy_rtx (VINSN_LHS (vi)); | 844 lhs_rtx = copy_rtx (VINSN_LHS (vi)); |
890 | 845 |
891 pattern = gen_rtx_SET (VOIDmode, lhs_rtx, rhs_rtx); | 846 pattern = gen_rtx_SET (lhs_rtx, rhs_rtx); |
892 insn_rtx = create_insn_rtx_from_pattern (pattern, NULL_RTX); | 847 insn_rtx = create_insn_rtx_from_pattern (pattern, NULL_RTX); |
893 | 848 |
894 return insn_rtx; | 849 return insn_rtx; |
895 } | 850 } |
896 | 851 |
917 | 872 |
918 static bool | 873 static bool |
919 replace_src_with_reg_ok_p (insn_t insn, rtx new_src_reg) | 874 replace_src_with_reg_ok_p (insn_t insn, rtx new_src_reg) |
920 { | 875 { |
921 vinsn_t vi = INSN_VINSN (insn); | 876 vinsn_t vi = INSN_VINSN (insn); |
922 enum machine_mode mode; | 877 machine_mode mode; |
923 rtx dst_loc; | 878 rtx dst_loc; |
924 bool res; | 879 bool res; |
925 | 880 |
926 gcc_assert (VINSN_SEPARABLE_P (vi)); | 881 gcc_assert (VINSN_SEPARABLE_P (vi)); |
927 | 882 |
958 | 913 |
959 return res; | 914 return res; |
960 } | 915 } |
961 | 916 |
962 /* Create a pattern with rhs of VI and lhs of LHS_RTX. */ | 917 /* Create a pattern with rhs of VI and lhs of LHS_RTX. */ |
963 static rtx | 918 static rtx_insn * |
964 create_insn_rtx_with_lhs (vinsn_t vi, rtx lhs_rtx) | 919 create_insn_rtx_with_lhs (vinsn_t vi, rtx lhs_rtx) |
965 { | 920 { |
966 rtx rhs_rtx; | 921 rtx rhs_rtx; |
967 rtx pattern; | 922 rtx pattern; |
968 rtx insn_rtx; | 923 rtx_insn *insn_rtx; |
969 | 924 |
970 rhs_rtx = copy_rtx (VINSN_RHS (vi)); | 925 rhs_rtx = copy_rtx (VINSN_RHS (vi)); |
971 | 926 |
972 pattern = gen_rtx_SET (VOIDmode, lhs_rtx, rhs_rtx); | 927 pattern = gen_rtx_SET (lhs_rtx, rhs_rtx); |
973 insn_rtx = create_insn_rtx_from_pattern (pattern, NULL_RTX); | 928 insn_rtx = create_insn_rtx_from_pattern (pattern, NULL_RTX); |
974 | 929 |
975 return insn_rtx; | 930 return insn_rtx; |
976 } | 931 } |
977 | 932 |
978 /* Substitute lhs in the given expression EXPR for the register with number | 933 /* Substitute lhs in the given expression EXPR for the register with number |
979 NEW_REGNO. SET_DEST may be arbitrary rtx, not only register. */ | 934 NEW_REGNO. SET_DEST may be arbitrary rtx, not only register. */ |
980 static void | 935 static void |
981 replace_dest_with_reg_in_expr (expr_t expr, rtx new_reg) | 936 replace_dest_with_reg_in_expr (expr_t expr, rtx new_reg) |
982 { | 937 { |
983 rtx insn_rtx; | 938 rtx_insn *insn_rtx; |
984 vinsn_t vinsn; | 939 vinsn_t vinsn; |
985 | 940 |
986 insn_rtx = create_insn_rtx_with_lhs (EXPR_VINSN (expr), new_reg); | 941 insn_rtx = create_insn_rtx_with_lhs (EXPR_VINSN (expr), new_reg); |
987 vinsn = create_vinsn_from_insn_rtx (insn_rtx, false); | 942 vinsn = create_vinsn_from_insn_rtx (insn_rtx, false); |
988 | 943 |
1025 Returns NO_REGS for call insns because some targets have constraints on | 980 Returns NO_REGS for call insns because some targets have constraints on |
1026 destination register of a call insn. | 981 destination register of a call insn. |
1027 | 982 |
1028 Code adopted from regrename.c::build_def_use. */ | 983 Code adopted from regrename.c::build_def_use. */ |
1029 static enum reg_class | 984 static enum reg_class |
1030 get_reg_class (rtx insn) | 985 get_reg_class (rtx_insn *insn) |
1031 { | 986 { |
1032 int alt, i, n_ops; | 987 int i, n_ops; |
1033 | 988 |
1034 extract_insn (insn); | 989 extract_constrain_insn (insn); |
1035 if (! constrain_operands (1)) | 990 preprocess_constraints (insn); |
1036 fatal_insn_not_found (insn); | |
1037 preprocess_constraints (); | |
1038 alt = which_alternative; | |
1039 n_ops = recog_data.n_operands; | 991 n_ops = recog_data.n_operands; |
1040 | 992 |
1041 for (i = 0; i < n_ops; ++i) | 993 const operand_alternative *op_alt = which_op_alt (); |
1042 { | |
1043 int matches = recog_op_alt[i][alt].matches; | |
1044 if (matches >= 0) | |
1045 recog_op_alt[i][alt].cl = recog_op_alt[matches][alt].cl; | |
1046 } | |
1047 | |
1048 if (asm_noperands (PATTERN (insn)) > 0) | 994 if (asm_noperands (PATTERN (insn)) > 0) |
1049 { | 995 { |
1050 for (i = 0; i < n_ops; i++) | 996 for (i = 0; i < n_ops; i++) |
1051 if (recog_data.operand_type[i] == OP_OUT) | 997 if (recog_data.operand_type[i] == OP_OUT) |
1052 { | 998 { |
1053 rtx *loc = recog_data.operand_loc[i]; | 999 rtx *loc = recog_data.operand_loc[i]; |
1054 rtx op = *loc; | 1000 rtx op = *loc; |
1055 enum reg_class cl = recog_op_alt[i][alt].cl; | 1001 enum reg_class cl = alternative_class (op_alt, i); |
1056 | 1002 |
1057 if (REG_P (op) | 1003 if (REG_P (op) |
1058 && REGNO (op) == ORIGINAL_REGNO (op)) | 1004 && REGNO (op) == ORIGINAL_REGNO (op)) |
1059 continue; | 1005 continue; |
1060 | 1006 |
1064 else if (!CALL_P (insn)) | 1010 else if (!CALL_P (insn)) |
1065 { | 1011 { |
1066 for (i = 0; i < n_ops + recog_data.n_dups; i++) | 1012 for (i = 0; i < n_ops + recog_data.n_dups; i++) |
1067 { | 1013 { |
1068 int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops]; | 1014 int opn = i < n_ops ? i : recog_data.dup_num[i - n_ops]; |
1069 enum reg_class cl = recog_op_alt[opn][alt].cl; | 1015 enum reg_class cl = alternative_class (op_alt, opn); |
1070 | 1016 |
1071 if (recog_data.operand_type[opn] == OP_OUT || | 1017 if (recog_data.operand_type[opn] == OP_OUT || |
1072 recog_data.operand_type[opn] == OP_INOUT) | 1018 recog_data.operand_type[opn] == OP_INOUT) |
1073 return cl; | 1019 return cl; |
1074 } | 1020 } |
1079 may result in returning NO_REGS, cause flags is written implicitly through | 1025 may result in returning NO_REGS, cause flags is written implicitly through |
1080 CMP insn, which has no OP_OUT | OP_INOUT operands. */ | 1026 CMP insn, which has no OP_OUT | OP_INOUT operands. */ |
1081 return NO_REGS; | 1027 return NO_REGS; |
1082 } | 1028 } |
1083 | 1029 |
1084 #ifdef HARD_REGNO_RENAME_OK | |
1085 /* Calculate HARD_REGNO_RENAME_OK data for REGNO. */ | 1030 /* Calculate HARD_REGNO_RENAME_OK data for REGNO. */ |
1086 static void | 1031 static void |
1087 init_hard_regno_rename (int regno) | 1032 init_hard_regno_rename (int regno) |
1088 { | 1033 { |
1089 int cur_reg; | 1034 int cur_reg; |
1098 | 1043 |
1099 if (HARD_REGNO_RENAME_OK (regno, cur_reg)) | 1044 if (HARD_REGNO_RENAME_OK (regno, cur_reg)) |
1100 SET_HARD_REG_BIT (sel_hrd.regs_for_rename[regno], cur_reg); | 1045 SET_HARD_REG_BIT (sel_hrd.regs_for_rename[regno], cur_reg); |
1101 } | 1046 } |
1102 } | 1047 } |
1103 #endif | |
1104 | 1048 |
1105 /* A wrapper around HARD_REGNO_RENAME_OK that will look into the hard regs | 1049 /* A wrapper around HARD_REGNO_RENAME_OK that will look into the hard regs |
1106 data first. */ | 1050 data first. */ |
1107 static inline bool | 1051 static inline bool |
1108 sel_hard_regno_rename_ok (int from ATTRIBUTE_UNUSED, int to ATTRIBUTE_UNUSED) | 1052 sel_hard_regno_rename_ok (int from ATTRIBUTE_UNUSED, int to ATTRIBUTE_UNUSED) |
1109 { | 1053 { |
1110 #ifdef HARD_REGNO_RENAME_OK | |
1111 /* Check whether this is all calculated. */ | 1054 /* Check whether this is all calculated. */ |
1112 if (TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], from)) | 1055 if (TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], from)) |
1113 return TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], to); | 1056 return TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], to); |
1114 | 1057 |
1115 init_hard_regno_rename (from); | 1058 init_hard_regno_rename (from); |
1116 | 1059 |
1117 return TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], to); | 1060 return TEST_HARD_REG_BIT (sel_hrd.regs_for_rename[from], to); |
1118 #else | |
1119 return true; | |
1120 #endif | |
1121 } | 1061 } |
1122 | 1062 |
1123 /* Calculate set of registers that are capable of holding MODE. */ | 1063 /* Calculate set of registers that are capable of holding MODE. */ |
1124 static void | 1064 static void |
1125 init_regs_for_mode (enum machine_mode mode) | 1065 init_regs_for_mode (machine_mode mode) |
1126 { | 1066 { |
1127 int cur_reg; | 1067 int cur_reg; |
1128 | 1068 |
1129 CLEAR_HARD_REG_SET (sel_hrd.regs_for_mode[mode]); | 1069 CLEAR_HARD_REG_SET (sel_hrd.regs_for_mode[mode]); |
1130 CLEAR_HARD_REG_SET (sel_hrd.regs_for_call_clobbered[mode]); | 1070 CLEAR_HARD_REG_SET (sel_hrd.regs_for_call_clobbered[mode]); |
1131 | 1071 |
1132 for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++) | 1072 for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++) |
1133 { | 1073 { |
1134 int nregs = hard_regno_nregs[cur_reg][mode]; | 1074 int nregs; |
1135 int i; | 1075 int i; |
1076 | |
1077 /* See whether it accepts all modes that occur in | |
1078 original insns. */ | |
1079 if (!targetm.hard_regno_mode_ok (cur_reg, mode)) | |
1080 continue; | |
1081 | |
1082 nregs = hard_regno_nregs (cur_reg, mode); | |
1136 | 1083 |
1137 for (i = nregs - 1; i >= 0; --i) | 1084 for (i = nregs - 1; i >= 0; --i) |
1138 if (fixed_regs[cur_reg + i] | 1085 if (fixed_regs[cur_reg + i] |
1139 || global_regs[cur_reg + i] | 1086 || global_regs[cur_reg + i] |
1140 /* Can't use regs which aren't saved by | 1087 /* Can't use regs which aren't saved by |
1144 it affects aliasing globally and invalidates all AV sets. */ | 1091 it affects aliasing globally and invalidates all AV sets. */ |
1145 || get_reg_base_value (cur_reg + i) | 1092 || get_reg_base_value (cur_reg + i) |
1146 #ifdef LEAF_REGISTERS | 1093 #ifdef LEAF_REGISTERS |
1147 /* We can't use a non-leaf register if we're in a | 1094 /* We can't use a non-leaf register if we're in a |
1148 leaf function. */ | 1095 leaf function. */ |
1149 || (current_function_is_leaf | 1096 || (crtl->is_leaf |
1150 && !LEAF_REGISTERS[cur_reg + i]) | 1097 && !LEAF_REGISTERS[cur_reg + i]) |
1151 #endif | 1098 #endif |
1152 ) | 1099 ) |
1153 break; | 1100 break; |
1154 | 1101 |
1155 if (i >= 0) | 1102 if (i >= 0) |
1156 continue; | 1103 continue; |
1157 | 1104 |
1158 /* See whether it accepts all modes that occur in | 1105 if (targetm.hard_regno_call_part_clobbered (cur_reg, mode)) |
1159 original insns. */ | |
1160 if (! HARD_REGNO_MODE_OK (cur_reg, mode)) | |
1161 continue; | |
1162 | |
1163 if (HARD_REGNO_CALL_PART_CLOBBERED (cur_reg, mode)) | |
1164 SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode], | 1106 SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode], |
1165 cur_reg); | 1107 cur_reg); |
1166 | 1108 |
1167 /* If the CUR_REG passed all the checks above, | 1109 /* If the CUR_REG passed all the checks above, |
1168 then it's ok. */ | 1110 then it's ok. */ |
1211 | 1153 |
1212 static void | 1154 static void |
1213 mark_unavailable_hard_regs (def_t def, struct reg_rename *reg_rename_p, | 1155 mark_unavailable_hard_regs (def_t def, struct reg_rename *reg_rename_p, |
1214 regset used_regs ATTRIBUTE_UNUSED) | 1156 regset used_regs ATTRIBUTE_UNUSED) |
1215 { | 1157 { |
1216 enum machine_mode mode; | 1158 machine_mode mode; |
1217 enum reg_class cl = NO_REGS; | 1159 enum reg_class cl = NO_REGS; |
1218 rtx orig_dest; | 1160 rtx orig_dest; |
1219 unsigned cur_reg, regno; | 1161 unsigned cur_reg, regno; |
1220 hard_reg_set_iterator hrsi; | 1162 hard_reg_set_iterator hrsi; |
1221 | 1163 |
1240 | 1182 |
1241 /* Stop if the original register is one of the fixed_regs, global_regs or | 1183 /* Stop if the original register is one of the fixed_regs, global_regs or |
1242 frame pointer, or we could not discover its class. */ | 1184 frame pointer, or we could not discover its class. */ |
1243 if (fixed_regs[regno] | 1185 if (fixed_regs[regno] |
1244 || global_regs[regno] | 1186 || global_regs[regno] |
1245 #if !HARD_FRAME_POINTER_IS_FRAME_POINTER | 1187 || (!HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed |
1246 || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM) | 1188 && regno == HARD_FRAME_POINTER_REGNUM) |
1247 #else | 1189 || (HARD_FRAME_POINTER_IS_FRAME_POINTER && frame_pointer_needed |
1248 || (frame_pointer_needed && regno == FRAME_POINTER_REGNUM) | 1190 && regno == FRAME_POINTER_REGNUM) |
1249 #endif | |
1250 || (reload_completed && cl == NO_REGS)) | 1191 || (reload_completed && cl == NO_REGS)) |
1251 { | 1192 { |
1252 SET_HARD_REG_SET (reg_rename_p->unavailable_hard_regs); | 1193 SET_HARD_REG_SET (reg_rename_p->unavailable_hard_regs); |
1253 | 1194 |
1254 /* Give a chance for original register, if it isn't in used_regs. */ | 1195 /* Give a chance for original register, if it isn't in used_regs. */ |
1261 /* If something allocated on stack in this function, mark frame pointer | 1202 /* If something allocated on stack in this function, mark frame pointer |
1262 register unavailable, considering also modes. | 1203 register unavailable, considering also modes. |
1263 FIXME: it is enough to do this once per all original defs. */ | 1204 FIXME: it is enough to do this once per all original defs. */ |
1264 if (frame_pointer_needed) | 1205 if (frame_pointer_needed) |
1265 { | 1206 { |
1266 int i; | 1207 add_to_hard_reg_set (®_rename_p->unavailable_hard_regs, |
1267 | 1208 Pmode, FRAME_POINTER_REGNUM); |
1268 for (i = hard_regno_nregs[FRAME_POINTER_REGNUM][Pmode]; i--;) | 1209 |
1269 SET_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, | 1210 if (!HARD_FRAME_POINTER_IS_FRAME_POINTER) |
1270 FRAME_POINTER_REGNUM + i); | 1211 add_to_hard_reg_set (®_rename_p->unavailable_hard_regs, |
1271 | 1212 Pmode, HARD_FRAME_POINTER_REGNUM); |
1272 #if !HARD_FRAME_POINTER_IS_FRAME_POINTER | |
1273 for (i = hard_regno_nregs[HARD_FRAME_POINTER_REGNUM][Pmode]; i--;) | |
1274 SET_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, | |
1275 HARD_FRAME_POINTER_REGNUM + i); | |
1276 #endif | |
1277 } | 1213 } |
1278 | 1214 |
1279 #ifdef STACK_REGS | 1215 #ifdef STACK_REGS |
1280 /* For the stack registers the presence of FIRST_STACK_REG in USED_REGS | 1216 /* For the stack registers the presence of FIRST_STACK_REG in USED_REGS |
1281 is equivalent to as if all stack regs were in this set. | 1217 is equivalent to as if all stack regs were in this set. |
1313 AND_HARD_REG_SET (reg_rename_p->available_for_renaming, | 1249 AND_HARD_REG_SET (reg_rename_p->available_for_renaming, |
1314 sel_hrd.regs_for_mode[mode]); | 1250 sel_hrd.regs_for_mode[mode]); |
1315 | 1251 |
1316 /* Exclude registers that are partially call clobbered. */ | 1252 /* Exclude registers that are partially call clobbered. */ |
1317 if (def->crosses_call | 1253 if (def->crosses_call |
1318 && ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) | 1254 && !targetm.hard_regno_call_part_clobbered (regno, mode)) |
1319 AND_COMPL_HARD_REG_SET (reg_rename_p->available_for_renaming, | 1255 AND_COMPL_HARD_REG_SET (reg_rename_p->available_for_renaming, |
1320 sel_hrd.regs_for_call_clobbered[mode]); | 1256 sel_hrd.regs_for_call_clobbered[mode]); |
1321 | 1257 |
1322 /* Leave only those that are ok to rename. */ | 1258 /* Leave only those that are ok to rename. */ |
1323 EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming, | 1259 EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming, |
1324 0, cur_reg, hrsi) | 1260 0, cur_reg, hrsi) |
1325 { | 1261 { |
1326 int nregs; | 1262 int nregs; |
1327 int i; | 1263 int i; |
1328 | 1264 |
1329 nregs = hard_regno_nregs[cur_reg][mode]; | 1265 nregs = hard_regno_nregs (cur_reg, mode); |
1330 gcc_assert (nregs > 0); | 1266 gcc_assert (nregs > 0); |
1331 | 1267 |
1332 for (i = nregs - 1; i >= 0; --i) | 1268 for (i = nregs - 1; i >= 0; --i) |
1333 if (! sel_hard_regno_rename_ok (regno + i, cur_reg + i)) | 1269 if (! sel_hard_regno_rename_ok (regno + i, cur_reg + i)) |
1334 break; | 1270 break; |
1386 struct reg_rename *reg_rename_p, | 1322 struct reg_rename *reg_rename_p, |
1387 def_list_t original_insns, bool *is_orig_reg_p_ptr) | 1323 def_list_t original_insns, bool *is_orig_reg_p_ptr) |
1388 { | 1324 { |
1389 int best_new_reg; | 1325 int best_new_reg; |
1390 unsigned cur_reg; | 1326 unsigned cur_reg; |
1391 enum machine_mode mode = VOIDmode; | 1327 machine_mode mode = VOIDmode; |
1392 unsigned regno, i, n; | 1328 unsigned regno, i, n; |
1393 hard_reg_set_iterator hrsi; | 1329 hard_reg_set_iterator hrsi; |
1394 def_list_iterator di; | 1330 def_list_iterator di; |
1395 def_t def; | 1331 def_t def; |
1396 | 1332 |
1410 if (mode == VOIDmode) | 1346 if (mode == VOIDmode) |
1411 mode = GET_MODE (orig_dest); | 1347 mode = GET_MODE (orig_dest); |
1412 gcc_assert (mode == GET_MODE (orig_dest)); | 1348 gcc_assert (mode == GET_MODE (orig_dest)); |
1413 | 1349 |
1414 regno = REGNO (orig_dest); | 1350 regno = REGNO (orig_dest); |
1415 for (i = 0, n = hard_regno_nregs[regno][mode]; i < n; i++) | 1351 for (i = 0, n = REG_NREGS (orig_dest); i < n; i++) |
1416 if (TEST_HARD_REG_BIT (hard_regs_used, regno + i)) | 1352 if (TEST_HARD_REG_BIT (hard_regs_used, regno + i)) |
1417 break; | 1353 break; |
1418 | 1354 |
1419 /* All hard registers are available. */ | 1355 /* All hard registers are available. */ |
1420 if (i == n) | 1356 if (i == n) |
1434 EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming, | 1370 EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming, |
1435 0, cur_reg, hrsi) | 1371 0, cur_reg, hrsi) |
1436 if (! TEST_HARD_REG_BIT (hard_regs_used, cur_reg)) | 1372 if (! TEST_HARD_REG_BIT (hard_regs_used, cur_reg)) |
1437 { | 1373 { |
1438 /* Check that all hard regs for mode are available. */ | 1374 /* Check that all hard regs for mode are available. */ |
1439 for (i = 1, n = hard_regno_nregs[cur_reg][mode]; i < n; i++) | 1375 for (i = 1, n = hard_regno_nregs (cur_reg, mode); i < n; i++) |
1440 if (TEST_HARD_REG_BIT (hard_regs_used, cur_reg + i) | 1376 if (TEST_HARD_REG_BIT (hard_regs_used, cur_reg + i) |
1441 || !TEST_HARD_REG_BIT (reg_rename_p->available_for_renaming, | 1377 || !TEST_HARD_REG_BIT (reg_rename_p->available_for_renaming, |
1442 cur_reg + i)) | 1378 cur_reg + i)) |
1443 break; | 1379 break; |
1444 | 1380 |
1497 struct reg_rename *reg_rename_p, | 1433 struct reg_rename *reg_rename_p, |
1498 def_list_t original_insns, bool *is_orig_reg_p_ptr) | 1434 def_list_t original_insns, bool *is_orig_reg_p_ptr) |
1499 { | 1435 { |
1500 def_list_iterator i; | 1436 def_list_iterator i; |
1501 def_t def; | 1437 def_t def; |
1502 enum machine_mode mode = VOIDmode; | 1438 machine_mode mode = VOIDmode; |
1503 bool bad_hard_regs = false; | 1439 bool bad_hard_regs = false; |
1504 | 1440 |
1505 /* We should not use this after reload. */ | 1441 /* We should not use this after reload. */ |
1506 gcc_assert (!reload_completed); | 1442 gcc_assert (!reload_completed); |
1507 | 1443 |
1520 mode = GET_MODE (dest); | 1456 mode = GET_MODE (dest); |
1521 else | 1457 else |
1522 gcc_assert (mode == GET_MODE (dest)); | 1458 gcc_assert (mode == GET_MODE (dest)); |
1523 orig_regno = REGNO (dest); | 1459 orig_regno = REGNO (dest); |
1524 | 1460 |
1525 if (!REGNO_REG_SET_P (used_regs, orig_regno)) | 1461 /* Check that nothing in used_regs intersects with orig_regno. When |
1526 { | 1462 we have a hard reg here, still loop over hard_regno_nregs. */ |
1527 if (orig_regno < FIRST_PSEUDO_REGISTER) | 1463 if (HARD_REGISTER_NUM_P (orig_regno)) |
1528 { | 1464 { |
1529 gcc_assert (df_regs_ever_live_p (orig_regno)); | 1465 int j, n; |
1530 | 1466 for (j = 0, n = REG_NREGS (dest); j < n; j++) |
1531 /* For hard registers, we have to check hardware imposed | 1467 if (REGNO_REG_SET_P (used_regs, orig_regno + j)) |
1532 limitations (frame/stack registers, calls crossed). */ | 1468 break; |
1533 if (!TEST_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, | 1469 if (j < n) |
1534 orig_regno)) | 1470 continue; |
1535 { | 1471 } |
1536 /* Don't let register cross a call if it doesn't already | 1472 else |
1537 cross one. This condition is written in accordance with | 1473 { |
1538 that in sched-deps.c sched_analyze_reg(). */ | 1474 if (REGNO_REG_SET_P (used_regs, orig_regno)) |
1539 if (!reg_rename_p->crosses_call | 1475 continue; |
1540 || REG_N_CALLS_CROSSED (orig_regno) > 0) | 1476 } |
1541 return gen_rtx_REG (mode, orig_regno); | 1477 if (HARD_REGISTER_NUM_P (orig_regno)) |
1542 } | 1478 { |
1543 | 1479 gcc_assert (df_regs_ever_live_p (orig_regno)); |
1544 bad_hard_regs = true; | 1480 |
1545 } | 1481 /* For hard registers, we have to check hardware imposed |
1546 else | 1482 limitations (frame/stack registers, calls crossed). */ |
1547 return dest; | 1483 if (!TEST_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, |
1548 } | 1484 orig_regno)) |
1549 } | 1485 { |
1486 /* Don't let register cross a call if it doesn't already | |
1487 cross one. This condition is written in accordance with | |
1488 that in sched-deps.c sched_analyze_reg(). */ | |
1489 if (!reg_rename_p->crosses_call | |
1490 || REG_N_CALLS_CROSSED (orig_regno) > 0) | |
1491 return gen_rtx_REG (mode, orig_regno); | |
1492 } | |
1493 | |
1494 bad_hard_regs = true; | |
1495 } | |
1496 else | |
1497 return dest; | |
1498 } | |
1550 | 1499 |
1551 *is_orig_reg_p_ptr = false; | 1500 *is_orig_reg_p_ptr = false; |
1552 | 1501 |
1553 /* We had some original hard registers that couldn't be used. | 1502 /* We had some original hard registers that couldn't be used. |
1554 Those were likely special. Don't try to create a pseudo. */ | 1503 Those were likely special. Don't try to create a pseudo. */ |
1575 static void | 1524 static void |
1576 verify_target_availability (expr_t expr, regset used_regs, | 1525 verify_target_availability (expr_t expr, regset used_regs, |
1577 struct reg_rename *reg_rename_p) | 1526 struct reg_rename *reg_rename_p) |
1578 { | 1527 { |
1579 unsigned n, i, regno; | 1528 unsigned n, i, regno; |
1580 enum machine_mode mode; | 1529 machine_mode mode; |
1581 bool target_available, live_available, hard_available; | 1530 bool target_available, live_available, hard_available; |
1582 | 1531 |
1583 if (!REG_P (EXPR_LHS (expr)) || EXPR_TARGET_AVAILABLE (expr) < 0) | 1532 if (!REG_P (EXPR_LHS (expr)) || EXPR_TARGET_AVAILABLE (expr) < 0) |
1584 return; | 1533 return; |
1585 | 1534 |
1586 regno = expr_dest_regno (expr); | 1535 regno = expr_dest_regno (expr); |
1587 mode = GET_MODE (EXPR_LHS (expr)); | 1536 mode = GET_MODE (EXPR_LHS (expr)); |
1588 target_available = EXPR_TARGET_AVAILABLE (expr) == 1; | 1537 target_available = EXPR_TARGET_AVAILABLE (expr) == 1; |
1589 n = reload_completed ? hard_regno_nregs[regno][mode] : 1; | 1538 n = HARD_REGISTER_NUM_P (regno) ? hard_regno_nregs (regno, mode) : 1; |
1590 | 1539 |
1591 live_available = hard_available = true; | 1540 live_available = hard_available = true; |
1592 for (i = 0; i < n; i++) | 1541 for (i = 0; i < n; i++) |
1593 { | 1542 { |
1594 if (bitmap_bit_p (used_regs, regno + i)) | 1543 if (bitmap_bit_p (used_regs, regno + i)) |
1710 CLEAR_HARD_REG_SET (reg_rename_data.unavailable_hard_regs); | 1659 CLEAR_HARD_REG_SET (reg_rename_data.unavailable_hard_regs); |
1711 | 1660 |
1712 collect_unavailable_regs_from_bnds (expr, bnds, used_regs, ®_rename_data, | 1661 collect_unavailable_regs_from_bnds (expr, bnds, used_regs, ®_rename_data, |
1713 &original_insns); | 1662 &original_insns); |
1714 | 1663 |
1715 #ifdef ENABLE_CHECKING | |
1716 /* If after reload, make sure we're working with hard regs here. */ | 1664 /* If after reload, make sure we're working with hard regs here. */ |
1717 if (reload_completed) | 1665 if (flag_checking && reload_completed) |
1718 { | 1666 { |
1719 reg_set_iterator rsi; | 1667 reg_set_iterator rsi; |
1720 unsigned i; | 1668 unsigned i; |
1721 | 1669 |
1722 EXECUTE_IF_SET_IN_REG_SET (used_regs, FIRST_PSEUDO_REGISTER, i, rsi) | 1670 EXECUTE_IF_SET_IN_REG_SET (used_regs, FIRST_PSEUDO_REGISTER, i, rsi) |
1723 gcc_unreachable (); | 1671 gcc_unreachable (); |
1724 } | 1672 } |
1725 #endif | |
1726 | 1673 |
1727 if (EXPR_SEPARABLE_P (expr)) | 1674 if (EXPR_SEPARABLE_P (expr)) |
1728 { | 1675 { |
1729 rtx best_reg = NULL_RTX; | 1676 rtx best_reg = NULL_RTX; |
1730 /* Check that we have computed availability of a target register | 1677 /* Check that we have computed availability of a target register |
1825 ORIG_INSN is the original non-speculative insn in the stream. */ | 1772 ORIG_INSN is the original non-speculative insn in the stream. */ |
1826 static insn_t | 1773 static insn_t |
1827 create_speculation_check (expr_t c_expr, ds_t check_ds, insn_t orig_insn) | 1774 create_speculation_check (expr_t c_expr, ds_t check_ds, insn_t orig_insn) |
1828 { | 1775 { |
1829 rtx check_pattern; | 1776 rtx check_pattern; |
1830 rtx insn_rtx; | 1777 rtx_insn *insn_rtx; |
1831 insn_t insn; | 1778 insn_t insn; |
1832 basic_block recovery_block; | 1779 basic_block recovery_block; |
1833 rtx label; | 1780 rtx_insn *label; |
1834 | 1781 |
1835 /* Create a recovery block if target is going to emit branchy check, or if | 1782 /* Create a recovery block if target is going to emit branchy check, or if |
1836 ORIG_INSN was speculative already. */ | 1783 ORIG_INSN was speculative already. */ |
1837 if (targetm.sched.needs_block_p (check_ds) | 1784 if (targetm.sched.needs_block_p (check_ds) |
1838 || EXPR_SPEC_DONE_DS (INSN_EXPR (orig_insn)) != 0) | 1785 || EXPR_SPEC_DONE_DS (INSN_EXPR (orig_insn)) != 0) |
1841 label = BB_HEAD (recovery_block); | 1788 label = BB_HEAD (recovery_block); |
1842 } | 1789 } |
1843 else | 1790 else |
1844 { | 1791 { |
1845 recovery_block = NULL; | 1792 recovery_block = NULL; |
1846 label = NULL_RTX; | 1793 label = NULL; |
1847 } | 1794 } |
1848 | 1795 |
1849 /* Get pattern of the check. */ | 1796 /* Get pattern of the check. */ |
1850 check_pattern = targetm.sched.gen_spec_check (EXPR_INSN_RTX (c_expr), label, | 1797 check_pattern = targetm.sched.gen_spec_check (EXPR_INSN_RTX (c_expr), label, |
1851 check_ds); | 1798 check_ds); |
1894 return insn; | 1841 return insn; |
1895 } | 1842 } |
1896 | 1843 |
1897 /* True when INSN is a "regN = regN" copy. */ | 1844 /* True when INSN is a "regN = regN" copy. */ |
1898 static bool | 1845 static bool |
1899 identical_copy_p (rtx insn) | 1846 identical_copy_p (rtx_insn *insn) |
1900 { | 1847 { |
1901 rtx lhs, rhs, pat; | 1848 rtx lhs, rhs, pat; |
1902 | 1849 |
1903 pat = PATTERN (insn); | 1850 pat = PATTERN (insn); |
1904 | 1851 |
1917 } | 1864 } |
1918 | 1865 |
1919 /* Undo all transformations on *AV_PTR that were done when | 1866 /* Undo all transformations on *AV_PTR that were done when |
1920 moving through INSN. */ | 1867 moving through INSN. */ |
1921 static void | 1868 static void |
1922 undo_transformations (av_set_t *av_ptr, rtx insn) | 1869 undo_transformations (av_set_t *av_ptr, rtx_insn *insn) |
1923 { | 1870 { |
1924 av_set_iterator av_iter; | 1871 av_set_iterator av_iter; |
1925 expr_t expr; | 1872 expr_t expr; |
1926 av_set_t new_set = NULL; | 1873 av_set_t new_set = NULL; |
1927 | 1874 |
1950 | 1897 |
1951 if (index >= 0) | 1898 if (index >= 0) |
1952 { | 1899 { |
1953 expr_history_def *phist; | 1900 expr_history_def *phist; |
1954 | 1901 |
1955 phist = VEC_index (expr_history_def, | 1902 phist = &EXPR_HISTORY_OF_CHANGES (expr)[index]; |
1956 EXPR_HISTORY_OF_CHANGES (expr), | |
1957 index); | |
1958 | 1903 |
1959 switch (phist->type) | 1904 switch (phist->type) |
1960 { | 1905 { |
1961 case TRANS_SPECULATION: | 1906 case TRANS_SPECULATION: |
1962 { | 1907 { |
2122 sel_print ("would create bookkeeping block: "); | 2067 sel_print ("would create bookkeeping block: "); |
2123 | 2068 |
2124 return TRUE; | 2069 return TRUE; |
2125 } | 2070 } |
2126 | 2071 |
2072 /* Return true when the conflict with newly created implicit clobbers | |
2073 between EXPR and THROUGH_INSN is found because of renaming. */ | |
2074 static bool | |
2075 implicit_clobber_conflict_p (insn_t through_insn, expr_t expr) | |
2076 { | |
2077 HARD_REG_SET temp; | |
2078 rtx_insn *insn; | |
2079 rtx reg, rhs, pat; | |
2080 hard_reg_set_iterator hrsi; | |
2081 unsigned regno; | |
2082 bool valid; | |
2083 | |
2084 /* Make a new pseudo register. */ | |
2085 reg = gen_reg_rtx (GET_MODE (EXPR_LHS (expr))); | |
2086 max_regno = max_reg_num (); | |
2087 maybe_extend_reg_info_p (); | |
2088 | |
2089 /* Validate a change and bail out early. */ | |
2090 insn = EXPR_INSN_RTX (expr); | |
2091 validate_change (insn, &SET_DEST (PATTERN (insn)), reg, true); | |
2092 valid = verify_changes (0); | |
2093 cancel_changes (0); | |
2094 if (!valid) | |
2095 { | |
2096 if (sched_verbose >= 6) | |
2097 sel_print ("implicit clobbers failed validation, "); | |
2098 return true; | |
2099 } | |
2100 | |
2101 /* Make a new insn with it. */ | |
2102 rhs = copy_rtx (VINSN_RHS (EXPR_VINSN (expr))); | |
2103 pat = gen_rtx_SET (reg, rhs); | |
2104 start_sequence (); | |
2105 insn = emit_insn (pat); | |
2106 end_sequence (); | |
2107 | |
2108 /* Calculate implicit clobbers. */ | |
2109 extract_insn (insn); | |
2110 preprocess_constraints (insn); | |
2111 alternative_mask prefrred = get_preferred_alternatives (insn); | |
2112 ira_implicitly_set_insn_hard_regs (&temp, prefrred); | |
2113 AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs); | |
2114 | |
2115 /* If any implicit clobber registers intersect with regular ones in | |
2116 through_insn, we have a dependency and thus bail out. */ | |
2117 EXECUTE_IF_SET_IN_HARD_REG_SET (temp, 0, regno, hrsi) | |
2118 { | |
2119 vinsn_t vi = INSN_VINSN (through_insn); | |
2120 if (bitmap_bit_p (VINSN_REG_SETS (vi), regno) | |
2121 || bitmap_bit_p (VINSN_REG_CLOBBERS (vi), regno) | |
2122 || bitmap_bit_p (VINSN_REG_USES (vi), regno)) | |
2123 return true; | |
2124 } | |
2125 | |
2126 return false; | |
2127 } | |
2128 | |
2127 /* Modifies EXPR so it can be moved through the THROUGH_INSN, | 2129 /* Modifies EXPR so it can be moved through the THROUGH_INSN, |
2128 performing necessary transformations. Record the type of transformation | 2130 performing necessary transformations. Record the type of transformation |
2129 made in PTRANS_TYPE, when it is not NULL. When INSIDE_INSN_GROUP, | 2131 made in PTRANS_TYPE, when it is not NULL. When INSIDE_INSN_GROUP, |
2130 permit all dependencies except true ones, and try to remove those | 2132 permit all dependencies except true ones, and try to remove those |
2131 too via forward substitution. All cases when a non-eliminable | 2133 too via forward substitution. All cases when a non-eliminable |
2254 Anyways, we should mark that the original register is | 2256 Anyways, we should mark that the original register is |
2255 unavailable. */ | 2257 unavailable. */ |
2256 if (!enable_schedule_as_rhs_p || !EXPR_SEPARABLE_P (expr)) | 2258 if (!enable_schedule_as_rhs_p || !EXPR_SEPARABLE_P (expr)) |
2257 return MOVEUP_EXPR_NULL; | 2259 return MOVEUP_EXPR_NULL; |
2258 | 2260 |
2261 /* When renaming a hard register to a pseudo before reload, extra | |
2262 dependencies can occur from the implicit clobbers of the insn. | |
2263 Filter out such cases here. */ | |
2264 if (!reload_completed && REG_P (EXPR_LHS (expr)) | |
2265 && HARD_REGISTER_P (EXPR_LHS (expr)) | |
2266 && implicit_clobber_conflict_p (through_insn, expr)) | |
2267 { | |
2268 if (sched_verbose >= 6) | |
2269 sel_print ("implicit clobbers conflict detected, "); | |
2270 return MOVEUP_EXPR_NULL; | |
2271 } | |
2259 EXPR_TARGET_AVAILABLE (expr) = false; | 2272 EXPR_TARGET_AVAILABLE (expr) = false; |
2260 was_target_conflict = true; | 2273 was_target_conflict = true; |
2261 as_rhs = true; | 2274 as_rhs = true; |
2262 } | 2275 } |
2263 | 2276 |
2514 dump_expr (expr); | 2527 dump_expr (expr); |
2515 sel_print (" through %d: ", INSN_UID (insn)); | 2528 sel_print (" through %d: ", INSN_UID (insn)); |
2516 } | 2529 } |
2517 | 2530 |
2518 if (DEBUG_INSN_P (EXPR_INSN_RTX (expr)) | 2531 if (DEBUG_INSN_P (EXPR_INSN_RTX (expr)) |
2532 && BLOCK_FOR_INSN (EXPR_INSN_RTX (expr)) | |
2519 && (sel_bb_head (BLOCK_FOR_INSN (EXPR_INSN_RTX (expr))) | 2533 && (sel_bb_head (BLOCK_FOR_INSN (EXPR_INSN_RTX (expr))) |
2520 == EXPR_INSN_RTX (expr))) | 2534 == EXPR_INSN_RTX (expr))) |
2521 /* Don't use cached information for debug insns that are heads of | 2535 /* Don't use cached information for debug insns that are heads of |
2522 basic blocks. */; | 2536 basic blocks. */; |
2523 else if (try_bitmap_cache (expr, insn, inside_insn_group, &res)) | 2537 else if (try_bitmap_cache (expr, insn, inside_insn_group, &res)) |
2744 sel_print ("\n"); | 2758 sel_print ("\n"); |
2745 if (sinfo->succs_ok_n != sinfo->all_succs_n) | 2759 if (sinfo->succs_ok_n != sinfo->all_succs_n) |
2746 sel_print ("real successors num: %d\n", sinfo->all_succs_n); | 2760 sel_print ("real successors num: %d\n", sinfo->all_succs_n); |
2747 } | 2761 } |
2748 | 2762 |
2749 /* Add insn to to the tail of current path. */ | 2763 /* Add insn to the tail of current path. */ |
2750 ilist_add (&p, insn); | 2764 ilist_add (&p, insn); |
2751 | 2765 |
2752 FOR_EACH_VEC_ELT (rtx, sinfo->succs_ok, is, succ) | 2766 FOR_EACH_VEC_ELT (sinfo->succs_ok, is, succ) |
2753 { | 2767 { |
2754 av_set_t succ_set; | 2768 av_set_t succ_set; |
2755 | 2769 |
2756 /* We will edit SUCC_SET and EXPR_SPEC field of its elements. */ | 2770 /* We will edit SUCC_SET and EXPR_SPEC field of its elements. */ |
2757 succ_set = compute_av_set_inside_bb (succ, p, ws, true); | 2771 succ_set = compute_av_set_inside_bb (succ, p, ws, true); |
2758 | 2772 |
2759 av_set_split_usefulness (succ_set, | 2773 av_set_split_usefulness (succ_set, |
2760 VEC_index (int, sinfo->probs_ok, is), | 2774 sinfo->probs_ok[is], |
2761 sinfo->all_prob); | 2775 sinfo->all_prob); |
2762 | 2776 |
2763 if (sinfo->all_succs_n > 1) | 2777 if (sinfo->all_succs_n > 1) |
2764 { | 2778 { |
2765 /* Find EXPR'es that came from *all* successors and save them | 2779 /* Find EXPR'es that came from *all* successors and save them |
2801 } | 2815 } |
2802 | 2816 |
2803 /* Check liveness restrictions via hard way when there are more than | 2817 /* Check liveness restrictions via hard way when there are more than |
2804 two successors. */ | 2818 two successors. */ |
2805 if (sinfo->succs_ok_n > 2) | 2819 if (sinfo->succs_ok_n > 2) |
2806 FOR_EACH_VEC_ELT (rtx, sinfo->succs_ok, is, succ) | 2820 FOR_EACH_VEC_ELT (sinfo->succs_ok, is, succ) |
2807 { | 2821 { |
2808 basic_block succ_bb = BLOCK_FOR_INSN (succ); | 2822 basic_block succ_bb = BLOCK_FOR_INSN (succ); |
2809 | 2823 |
2810 gcc_assert (BB_LV_SET_VALID_P (succ_bb)); | 2824 gcc_assert (BB_LV_SET_VALID_P (succ_bb)); |
2811 mark_unavailable_targets (av1, BB_AV_SET (succ_bb), | 2825 mark_unavailable_targets (av1, BB_AV_SET (succ_bb), |
2812 BB_LV_SET (succ_bb)); | 2826 BB_LV_SET (succ_bb)); |
2813 } | 2827 } |
2814 | 2828 |
2815 /* Finally, check liveness restrictions on paths leaving the region. */ | 2829 /* Finally, check liveness restrictions on paths leaving the region. */ |
2816 if (sinfo->all_succs_n > sinfo->succs_ok_n) | 2830 if (sinfo->all_succs_n > sinfo->succs_ok_n) |
2817 FOR_EACH_VEC_ELT (rtx, sinfo->succs_other, is, succ) | 2831 FOR_EACH_VEC_ELT (sinfo->succs_other, is, succ) |
2818 mark_unavailable_targets | 2832 mark_unavailable_targets |
2819 (av1, NULL, BB_LV_SET (BLOCK_FOR_INSN (succ))); | 2833 (av1, NULL, BB_LV_SET (BLOCK_FOR_INSN (succ))); |
2820 | 2834 |
2821 if (sinfo->all_succs_n > 1) | 2835 if (sinfo->all_succs_n > 1) |
2822 { | 2836 { |
3147 return lv; | 3161 return lv; |
3148 } | 3162 } |
3149 | 3163 |
3150 /* Update liveness sets for INSN. */ | 3164 /* Update liveness sets for INSN. */ |
3151 static inline void | 3165 static inline void |
3152 update_liveness_on_insn (rtx insn) | 3166 update_liveness_on_insn (rtx_insn *insn) |
3153 { | 3167 { |
3154 ignore_first = true; | 3168 ignore_first = true; |
3155 compute_live (insn); | 3169 compute_live (insn); |
3156 } | 3170 } |
3157 | 3171 |
3158 /* Compute liveness below INSN and write it into REGS. */ | 3172 /* Compute liveness below INSN and write it into REGS. */ |
3159 static inline void | 3173 static inline void |
3160 compute_live_below_insn (rtx insn, regset regs) | 3174 compute_live_below_insn (rtx_insn *insn, regset regs) |
3161 { | 3175 { |
3162 rtx succ; | 3176 rtx_insn *succ; |
3163 succ_iterator si; | 3177 succ_iterator si; |
3164 | 3178 |
3165 FOR_EACH_SUCC_1 (succ, si, insn, SUCCS_ALL) | 3179 FOR_EACH_SUCC_1 (succ, si, insn, SUCCS_ALL) |
3166 IOR_REG_SET (regs, compute_live (succ)); | 3180 IOR_REG_SET (regs, compute_live (succ)); |
3167 } | 3181 } |
3168 | 3182 |
3169 /* Update the data gathered in av and lv sets starting from INSN. */ | 3183 /* Update the data gathered in av and lv sets starting from INSN. */ |
3170 static void | 3184 static void |
3171 update_data_sets (rtx insn) | 3185 update_data_sets (rtx_insn *insn) |
3172 { | 3186 { |
3173 update_liveness_on_insn (insn); | 3187 update_liveness_on_insn (insn); |
3174 if (sel_bb_head_p (insn)) | 3188 if (sel_bb_head_p (insn)) |
3175 { | 3189 { |
3176 gcc_assert (AV_LEVEL (insn) != 0); | 3190 gcc_assert (AV_LEVEL (insn) != 0); |
3454 | 3468 |
3455 /* Filter speculative insns from AV_PTR if we don't want them. */ | 3469 /* Filter speculative insns from AV_PTR if we don't want them. */ |
3456 static void | 3470 static void |
3457 process_spec_exprs (av_set_t *av_ptr) | 3471 process_spec_exprs (av_set_t *av_ptr) |
3458 { | 3472 { |
3459 bool try_data_p = true; | |
3460 bool try_control_p = true; | |
3461 expr_t expr; | 3473 expr_t expr; |
3462 av_set_iterator si; | 3474 av_set_iterator si; |
3463 | 3475 |
3464 if (spec_info == NULL) | 3476 if (spec_info == NULL) |
3465 return; | 3477 return; |
3480 && (ds & DATA_SPEC) | 3492 && (ds & DATA_SPEC) |
3481 && (ds & CONTROL_SPEC)))) | 3493 && (ds & CONTROL_SPEC)))) |
3482 { | 3494 { |
3483 av_set_iter_remove (&si); | 3495 av_set_iter_remove (&si); |
3484 continue; | 3496 continue; |
3485 } | |
3486 | |
3487 if ((spec_info->flags & PREFER_NON_DATA_SPEC) | |
3488 && !(ds & BEGIN_DATA)) | |
3489 try_data_p = false; | |
3490 | |
3491 if ((spec_info->flags & PREFER_NON_CONTROL_SPEC) | |
3492 && !(ds & BEGIN_CONTROL)) | |
3493 try_control_p = false; | |
3494 } | |
3495 | |
3496 FOR_EACH_EXPR_1 (expr, si, av_ptr) | |
3497 { | |
3498 ds_t ds; | |
3499 | |
3500 ds = EXPR_SPEC_DONE_DS (expr); | |
3501 | |
3502 if (ds & SPECULATIVE) | |
3503 { | |
3504 if ((ds & BEGIN_DATA) && !try_data_p) | |
3505 /* We don't want any data speculative instructions right | |
3506 now. */ | |
3507 av_set_iter_remove (&si); | |
3508 | |
3509 if ((ds & BEGIN_CONTROL) && !try_control_p) | |
3510 /* We don't want any control speculative instructions right | |
3511 now. */ | |
3512 av_set_iter_remove (&si); | |
3513 } | 3497 } |
3514 } | 3498 } |
3515 } | 3499 } |
3516 | 3500 |
3517 /* Search for any use-like insns in AV_PTR and decide on scheduling | 3501 /* Search for any use-like insns in AV_PTR and decide on scheduling |
3576 } | 3560 } |
3577 | 3561 |
3578 return NULL; | 3562 return NULL; |
3579 } | 3563 } |
3580 | 3564 |
3581 /* Lookup EXPR in VINSN_VEC and return TRUE if found. */ | 3565 /* Lookup EXPR in VINSN_VEC and return TRUE if found. Also check patterns from |
3566 EXPR's history of changes. */ | |
3582 static bool | 3567 static bool |
3583 vinsn_vec_has_expr_p (vinsn_vec_t vinsn_vec, expr_t expr) | 3568 vinsn_vec_has_expr_p (vinsn_vec_t vinsn_vec, expr_t expr) |
3584 { | 3569 { |
3585 vinsn_t vinsn; | 3570 vinsn_t vinsn, expr_vinsn; |
3586 int n; | 3571 int n; |
3587 | 3572 unsigned i; |
3588 FOR_EACH_VEC_ELT (vinsn_t, vinsn_vec, n, vinsn) | 3573 |
3589 if (VINSN_SEPARABLE_P (vinsn)) | 3574 /* Start with checking expr itself and then proceed with all the old forms |
3590 { | 3575 of expr taken from its history vector. */ |
3591 if (vinsn_equal_p (vinsn, EXPR_VINSN (expr))) | 3576 for (i = 0, expr_vinsn = EXPR_VINSN (expr); |
3592 return true; | 3577 expr_vinsn; |
3593 } | 3578 expr_vinsn = (i < EXPR_HISTORY_OF_CHANGES (expr).length () |
3594 else | 3579 ? EXPR_HISTORY_OF_CHANGES (expr)[i++].old_expr_vinsn |
3595 { | 3580 : NULL)) |
3596 /* For non-separable instructions, the blocking insn can have | 3581 FOR_EACH_VEC_ELT (vinsn_vec, n, vinsn) |
3597 another pattern due to substitution, and we can't choose | 3582 if (VINSN_SEPARABLE_P (vinsn)) |
3598 different register as in the above case. Check all registers | 3583 { |
3599 being written instead. */ | 3584 if (vinsn_equal_p (vinsn, expr_vinsn)) |
3600 if (bitmap_intersect_p (VINSN_REG_SETS (vinsn), | 3585 return true; |
3601 VINSN_REG_SETS (EXPR_VINSN (expr)))) | 3586 } |
3602 return true; | 3587 else |
3603 } | 3588 { |
3589 /* For non-separable instructions, the blocking insn can have | |
3590 another pattern due to substitution, and we can't choose | |
3591 different register as in the above case. Check all registers | |
3592 being written instead. */ | |
3593 if (bitmap_intersect_p (VINSN_REG_SETS (vinsn), | |
3594 VINSN_REG_SETS (expr_vinsn))) | |
3595 return true; | |
3596 } | |
3604 | 3597 |
3605 return false; | 3598 return false; |
3606 } | 3599 } |
3607 | 3600 |
3608 #ifdef ENABLE_CHECKING | |
3609 /* Return true if either of expressions from ORIG_OPS can be blocked | 3601 /* Return true if either of expressions from ORIG_OPS can be blocked |
3610 by previously created bookkeeping code. STATIC_PARAMS points to static | 3602 by previously created bookkeeping code. STATIC_PARAMS points to static |
3611 parameters of move_op. */ | 3603 parameters of move_op. */ |
3612 static bool | 3604 static bool |
3613 av_set_could_be_blocked_by_bookkeeping_p (av_set_t orig_ops, void *static_params) | 3605 av_set_could_be_blocked_by_bookkeeping_p (av_set_t orig_ops, void *static_params) |
3634 | 3626 |
3635 /* Expressions in ORIG_OPS may have wrong destination register due to | 3627 /* Expressions in ORIG_OPS may have wrong destination register due to |
3636 renaming. Check with the right register instead. */ | 3628 renaming. Check with the right register instead. */ |
3637 if (sparams->dest && REG_P (sparams->dest)) | 3629 if (sparams->dest && REG_P (sparams->dest)) |
3638 { | 3630 { |
3639 unsigned regno = REGNO (sparams->dest); | 3631 rtx reg = sparams->dest; |
3640 vinsn_t failed_vinsn = INSN_VINSN (sparams->failed_insn); | 3632 vinsn_t failed_vinsn = INSN_VINSN (sparams->failed_insn); |
3641 | 3633 |
3642 if (bitmap_bit_p (VINSN_REG_SETS (failed_vinsn), regno) | 3634 if (register_unavailable_p (VINSN_REG_SETS (failed_vinsn), reg) |
3643 || bitmap_bit_p (VINSN_REG_USES (failed_vinsn), regno) | 3635 || register_unavailable_p (VINSN_REG_USES (failed_vinsn), reg) |
3644 || bitmap_bit_p (VINSN_REG_CLOBBERS (failed_vinsn), regno)) | 3636 || register_unavailable_p (VINSN_REG_CLOBBERS (failed_vinsn), reg)) |
3645 return true; | 3637 return true; |
3646 } | 3638 } |
3647 | 3639 |
3648 return false; | 3640 return false; |
3649 } | 3641 } |
3650 #endif | |
3651 | 3642 |
3652 /* Clear VINSN_VEC and detach vinsns. */ | 3643 /* Clear VINSN_VEC and detach vinsns. */ |
3653 static void | 3644 static void |
3654 vinsn_vec_clear (vinsn_vec_t *vinsn_vec) | 3645 vinsn_vec_clear (vinsn_vec_t *vinsn_vec) |
3655 { | 3646 { |
3656 unsigned len = VEC_length (vinsn_t, *vinsn_vec); | 3647 unsigned len = vinsn_vec->length (); |
3657 if (len > 0) | 3648 if (len > 0) |
3658 { | 3649 { |
3659 vinsn_t vinsn; | 3650 vinsn_t vinsn; |
3660 int n; | 3651 int n; |
3661 | 3652 |
3662 FOR_EACH_VEC_ELT (vinsn_t, *vinsn_vec, n, vinsn) | 3653 FOR_EACH_VEC_ELT (*vinsn_vec, n, vinsn) |
3663 vinsn_detach (vinsn); | 3654 vinsn_detach (vinsn); |
3664 VEC_block_remove (vinsn_t, *vinsn_vec, 0, len); | 3655 vinsn_vec->block_remove (0, len); |
3665 } | 3656 } |
3666 } | 3657 } |
3667 | 3658 |
3668 /* Add the vinsn of EXPR to the VINSN_VEC. */ | 3659 /* Add the vinsn of EXPR to the VINSN_VEC. */ |
3669 static void | 3660 static void |
3670 vinsn_vec_add (vinsn_vec_t *vinsn_vec, expr_t expr) | 3661 vinsn_vec_add (vinsn_vec_t *vinsn_vec, expr_t expr) |
3671 { | 3662 { |
3672 vinsn_attach (EXPR_VINSN (expr)); | 3663 vinsn_attach (EXPR_VINSN (expr)); |
3673 VEC_safe_push (vinsn_t, heap, *vinsn_vec, EXPR_VINSN (expr)); | 3664 vinsn_vec->safe_push (EXPR_VINSN (expr)); |
3674 } | 3665 } |
3675 | 3666 |
3676 /* Free the vector representing blocked expressions. */ | 3667 /* Free the vector representing blocked expressions. */ |
3677 static void | 3668 static void |
3678 vinsn_vec_free (vinsn_vec_t *vinsn_vec) | 3669 vinsn_vec_free (vinsn_vec_t &vinsn_vec) |
3679 { | 3670 { |
3680 if (*vinsn_vec) | 3671 vinsn_vec.release (); |
3681 VEC_free (vinsn_t, heap, *vinsn_vec); | |
3682 } | 3672 } |
3683 | 3673 |
3684 /* Increase EXPR_PRIORITY_ADJ for INSN by AMOUNT. */ | 3674 /* Increase EXPR_PRIORITY_ADJ for INSN by AMOUNT. */ |
3685 | 3675 |
3686 void sel_add_to_insn_priority (rtx insn, int amount) | 3676 void sel_add_to_insn_priority (rtx insn, int amount) |
3713 already scheduled. */ | 3703 already scheduled. */ |
3714 if (av == NULL) | 3704 if (av == NULL) |
3715 return false; | 3705 return false; |
3716 | 3706 |
3717 /* Empty vector from the previous stuff. */ | 3707 /* Empty vector from the previous stuff. */ |
3718 if (VEC_length (expr_t, vec_av_set) > 0) | 3708 if (vec_av_set.length () > 0) |
3719 VEC_block_remove (expr_t, vec_av_set, 0, VEC_length (expr_t, vec_av_set)); | 3709 vec_av_set.block_remove (0, vec_av_set.length ()); |
3720 | 3710 |
3721 /* Turn the set into a vector for sorting and call sel_target_adjust_priority | 3711 /* Turn the set into a vector for sorting and call sel_target_adjust_priority |
3722 for each insn. */ | 3712 for each insn. */ |
3723 gcc_assert (VEC_empty (expr_t, vec_av_set)); | 3713 gcc_assert (vec_av_set.is_empty ()); |
3724 FOR_EACH_EXPR (expr, si, av) | 3714 FOR_EACH_EXPR (expr, si, av) |
3725 { | 3715 { |
3726 VEC_safe_push (expr_t, heap, vec_av_set, expr); | 3716 vec_av_set.safe_push (expr); |
3727 | 3717 |
3728 gcc_assert (EXPR_PRIORITY_ADJ (expr) == 0 || *pneed_stall); | 3718 gcc_assert (EXPR_PRIORITY_ADJ (expr) == 0 || *pneed_stall); |
3729 | 3719 |
3730 /* Adjust priority using target backend hook. */ | 3720 /* Adjust priority using target backend hook. */ |
3731 sel_target_adjust_priority (expr); | 3721 sel_target_adjust_priority (expr); |
3732 } | 3722 } |
3733 | 3723 |
3734 /* Sort the vector. */ | 3724 /* Sort the vector. */ |
3735 VEC_qsort (expr_t, vec_av_set, sel_rank_for_schedule); | 3725 vec_av_set.qsort (sel_rank_for_schedule); |
3736 | 3726 |
3737 /* We record maximal priority of insns in av set for current instruction | 3727 /* We record maximal priority of insns in av set for current instruction |
3738 group. */ | 3728 group. */ |
3739 if (FENCE_STARTS_CYCLE_P (fence)) | 3729 if (FENCE_STARTS_CYCLE_P (fence)) |
3740 av_max_prio = est_ticks_till_branch = INT_MIN; | 3730 av_max_prio = est_ticks_till_branch = INT_MIN; |
3741 | 3731 |
3742 /* Filter out inappropriate expressions. Loop's direction is reversed to | 3732 /* Filter out inappropriate expressions. Loop's direction is reversed to |
3743 visit "best" instructions first. We assume that VEC_unordered_remove | 3733 visit "best" instructions first. We assume that vec::unordered_remove |
3744 moves last element in place of one being deleted. */ | 3734 moves last element in place of one being deleted. */ |
3745 for (n = VEC_length (expr_t, vec_av_set) - 1, stalled = 0; n >= 0; n--) | 3735 for (n = vec_av_set.length () - 1, stalled = 0; n >= 0; n--) |
3746 { | 3736 { |
3747 expr_t expr = VEC_index (expr_t, vec_av_set, n); | 3737 expr_t expr = vec_av_set[n]; |
3748 insn_t insn = EXPR_INSN_RTX (expr); | 3738 insn_t insn = EXPR_INSN_RTX (expr); |
3749 signed char target_available; | 3739 signed char target_available; |
3750 bool is_orig_reg_p = true; | 3740 bool is_orig_reg_p = true; |
3751 int need_cycles, new_prio; | 3741 int need_cycles, new_prio; |
3742 bool fence_insn_p = INSN_UID (insn) == INSN_UID (FENCE_INSN (fence)); | |
3752 | 3743 |
3753 /* Don't allow any insns other than from SCHED_GROUP if we have one. */ | 3744 /* Don't allow any insns other than from SCHED_GROUP if we have one. */ |
3754 if (FENCE_SCHED_NEXT (fence) && insn != FENCE_SCHED_NEXT (fence)) | 3745 if (FENCE_SCHED_NEXT (fence) && insn != FENCE_SCHED_NEXT (fence)) |
3755 { | 3746 { |
3756 VEC_unordered_remove (expr_t, vec_av_set, n); | 3747 vec_av_set.unordered_remove (n); |
3757 continue; | 3748 continue; |
3758 } | 3749 } |
3759 | 3750 |
3760 /* Set number of sched_next insns (just in case there | 3751 /* Set number of sched_next insns (just in case there |
3761 could be several). */ | 3752 could be several). */ |
3766 FIXME: try to minimize calls to this. */ | 3757 FIXME: try to minimize calls to this. */ |
3767 target_available = EXPR_TARGET_AVAILABLE (expr); | 3758 target_available = EXPR_TARGET_AVAILABLE (expr); |
3768 | 3759 |
3769 /* If insn was already scheduled on the current fence, | 3760 /* If insn was already scheduled on the current fence, |
3770 set TARGET_AVAILABLE to -1 no matter what expr's attribute says. */ | 3761 set TARGET_AVAILABLE to -1 no matter what expr's attribute says. */ |
3771 if (vinsn_vec_has_expr_p (vec_target_unavailable_vinsns, expr)) | 3762 if (vinsn_vec_has_expr_p (vec_target_unavailable_vinsns, expr) |
3763 && !fence_insn_p) | |
3772 target_available = -1; | 3764 target_available = -1; |
3773 | 3765 |
3774 /* If the availability of the EXPR is invalidated by the insertion of | 3766 /* If the availability of the EXPR is invalidated by the insertion of |
3775 bookkeeping earlier, make sure that we won't choose this expr for | 3767 bookkeeping earlier, make sure that we won't choose this expr for |
3776 scheduling if it's not separable, and if it is separable, then | 3768 scheduling if it's not separable, and if it is separable, then |
3777 we have to recompute the set of available registers for it. */ | 3769 we have to recompute the set of available registers for it. */ |
3778 if (vinsn_vec_has_expr_p (vec_bookkeeping_blocked_vinsns, expr)) | 3770 if (vinsn_vec_has_expr_p (vec_bookkeeping_blocked_vinsns, expr)) |
3779 { | 3771 { |
3780 VEC_unordered_remove (expr_t, vec_av_set, n); | 3772 vec_av_set.unordered_remove (n); |
3781 if (sched_verbose >= 4) | 3773 if (sched_verbose >= 4) |
3782 sel_print ("Expr %d is blocked by bookkeeping inserted earlier\n", | 3774 sel_print ("Expr %d is blocked by bookkeeping inserted earlier\n", |
3783 INSN_UID (insn)); | 3775 INSN_UID (insn)); |
3784 continue; | 3776 continue; |
3785 } | 3777 } |
3792 else if (/* Non-separable instruction will never | 3784 else if (/* Non-separable instruction will never |
3793 get another register. */ | 3785 get another register. */ |
3794 (target_available == false | 3786 (target_available == false |
3795 && !EXPR_SEPARABLE_P (expr)) | 3787 && !EXPR_SEPARABLE_P (expr)) |
3796 /* Don't try to find a register for low-priority expression. */ | 3788 /* Don't try to find a register for low-priority expression. */ |
3797 || (int) VEC_length (expr_t, vec_av_set) - 1 - n >= max_insns_to_rename | 3789 || (int) vec_av_set.length () - 1 - n >= max_insns_to_rename |
3798 /* ??? FIXME: Don't try to rename data speculation. */ | 3790 /* ??? FIXME: Don't try to rename data speculation. */ |
3799 || (EXPR_SPEC_DONE_DS (expr) & BEGIN_DATA) | 3791 || (EXPR_SPEC_DONE_DS (expr) & BEGIN_DATA) |
3800 || ! find_best_reg_for_expr (expr, bnds, &is_orig_reg_p)) | 3792 || ! find_best_reg_for_expr (expr, bnds, &is_orig_reg_p)) |
3801 { | 3793 { |
3802 VEC_unordered_remove (expr_t, vec_av_set, n); | 3794 vec_av_set.unordered_remove (n); |
3803 if (sched_verbose >= 4) | 3795 if (sched_verbose >= 4) |
3804 sel_print ("Expr %d has no suitable target register\n", | 3796 sel_print ("Expr %d has no suitable target register\n", |
3805 INSN_UID (insn)); | 3797 INSN_UID (insn)); |
3806 continue; | 3798 |
3799 /* A fence insn should not get here. */ | |
3800 gcc_assert (!fence_insn_p); | |
3801 continue; | |
3807 } | 3802 } |
3803 | |
3804 /* At this point a fence insn should always be available. */ | |
3805 gcc_assert (!fence_insn_p | |
3806 || INSN_UID (FENCE_INSN (fence)) == INSN_UID (EXPR_INSN_RTX (expr))); | |
3808 | 3807 |
3809 /* Filter expressions that need to be renamed or speculated when | 3808 /* Filter expressions that need to be renamed or speculated when |
3810 pipelining, because compensating register copies or speculation | 3809 pipelining, because compensating register copies or speculation |
3811 checks are likely to be placed near the beginning of the loop, | 3810 checks are likely to be placed near the beginning of the loop, |
3812 causing a stall. */ | 3811 causing a stall. */ |
3817 renaming/speculation to be successful. */ | 3816 renaming/speculation to be successful. */ |
3818 int need_n_ticks_till_branch = sel_vinsn_cost (EXPR_VINSN (expr)); | 3817 int need_n_ticks_till_branch = sel_vinsn_cost (EXPR_VINSN (expr)); |
3819 | 3818 |
3820 if ((int) current_loop_nest->ninsns < 9) | 3819 if ((int) current_loop_nest->ninsns < 9) |
3821 { | 3820 { |
3822 VEC_unordered_remove (expr_t, vec_av_set, n); | 3821 vec_av_set.unordered_remove (n); |
3823 if (sched_verbose >= 4) | 3822 if (sched_verbose >= 4) |
3824 sel_print ("Pipelining expr %d will likely cause stall\n", | 3823 sel_print ("Pipelining expr %d will likely cause stall\n", |
3825 INSN_UID (insn)); | 3824 INSN_UID (insn)); |
3826 continue; | 3825 continue; |
3827 } | 3826 } |
3828 | 3827 |
3829 if ((int) current_loop_nest->ninsns - num_insns_scheduled | 3828 if ((int) current_loop_nest->ninsns - num_insns_scheduled |
3830 < need_n_ticks_till_branch * issue_rate / 2 | 3829 < need_n_ticks_till_branch * issue_rate / 2 |
3831 && est_ticks_till_branch < need_n_ticks_till_branch) | 3830 && est_ticks_till_branch < need_n_ticks_till_branch) |
3832 { | 3831 { |
3833 VEC_unordered_remove (expr_t, vec_av_set, n); | 3832 vec_av_set.unordered_remove (n); |
3834 if (sched_verbose >= 4) | 3833 if (sched_verbose >= 4) |
3835 sel_print ("Pipelining expr %d will likely cause stall\n", | 3834 sel_print ("Pipelining expr %d will likely cause stall\n", |
3836 INSN_UID (insn)); | 3835 INSN_UID (insn)); |
3837 continue; | 3836 continue; |
3838 } | 3837 } |
3843 if (sel_insn_is_speculation_check (insn) | 3842 if (sel_insn_is_speculation_check (insn) |
3844 && EXPR_PRIORITY (expr) < av_max_prio) | 3843 && EXPR_PRIORITY (expr) < av_max_prio) |
3845 { | 3844 { |
3846 stalled++; | 3845 stalled++; |
3847 min_need_stall = min_need_stall < 0 ? 1 : MIN (min_need_stall, 1); | 3846 min_need_stall = min_need_stall < 0 ? 1 : MIN (min_need_stall, 1); |
3848 VEC_unordered_remove (expr_t, vec_av_set, n); | 3847 vec_av_set.unordered_remove (n); |
3849 if (sched_verbose >= 4) | 3848 if (sched_verbose >= 4) |
3850 sel_print ("Delaying speculation check %d until its first use\n", | 3849 sel_print ("Delaying speculation check %d until its first use\n", |
3851 INSN_UID (insn)); | 3850 INSN_UID (insn)); |
3852 continue; | 3851 continue; |
3853 } | 3852 } |
3870 { | 3869 { |
3871 stalled++; | 3870 stalled++; |
3872 min_need_stall = (min_need_stall < 0 | 3871 min_need_stall = (min_need_stall < 0 |
3873 ? need_cycles | 3872 ? need_cycles |
3874 : MIN (min_need_stall, need_cycles)); | 3873 : MIN (min_need_stall, need_cycles)); |
3875 VEC_unordered_remove (expr_t, vec_av_set, n); | 3874 vec_av_set.unordered_remove (n); |
3876 | 3875 |
3877 if (sched_verbose >= 4) | 3876 if (sched_verbose >= 4) |
3878 sel_print ("Expr %d is not ready until cycle %d (cached)\n", | 3877 sel_print ("Expr %d is not ready until cycle %d (cached)\n", |
3879 INSN_UID (insn), | 3878 INSN_UID (insn), |
3880 FENCE_READY_TICKS (fence)[INSN_UID (insn)]); | 3879 FENCE_READY_TICKS (fence)[INSN_UID (insn)]); |
3908 stalled++; | 3907 stalled++; |
3909 min_need_stall = (min_need_stall < 0 | 3908 min_need_stall = (min_need_stall < 0 |
3910 ? need_cycles | 3909 ? need_cycles |
3911 : MIN (min_need_stall, need_cycles)); | 3910 : MIN (min_need_stall, need_cycles)); |
3912 | 3911 |
3913 VEC_unordered_remove (expr_t, vec_av_set, n); | 3912 vec_av_set.unordered_remove (n); |
3914 | 3913 |
3915 if (sched_verbose >= 4) | 3914 if (sched_verbose >= 4) |
3916 sel_print ("Expr %d is not ready yet until cycle %d\n", | 3915 sel_print ("Expr %d is not ready yet until cycle %d\n", |
3917 INSN_UID (insn), | 3916 INSN_UID (insn), |
3918 FENCE_READY_TICKS (fence)[INSN_UID (insn)]); | 3917 FENCE_READY_TICKS (fence)[INSN_UID (insn)]); |
3926 | 3925 |
3927 /* Clear SCHED_NEXT. */ | 3926 /* Clear SCHED_NEXT. */ |
3928 if (FENCE_SCHED_NEXT (fence)) | 3927 if (FENCE_SCHED_NEXT (fence)) |
3929 { | 3928 { |
3930 gcc_assert (sched_next_worked == 1); | 3929 gcc_assert (sched_next_worked == 1); |
3931 FENCE_SCHED_NEXT (fence) = NULL_RTX; | 3930 FENCE_SCHED_NEXT (fence) = NULL; |
3932 } | 3931 } |
3933 | 3932 |
3934 /* No need to stall if this variable was not initialized. */ | 3933 /* No need to stall if this variable was not initialized. */ |
3935 if (min_need_stall < 0) | 3934 if (min_need_stall < 0) |
3936 min_need_stall = 0; | 3935 min_need_stall = 0; |
3937 | 3936 |
3938 if (VEC_empty (expr_t, vec_av_set)) | 3937 if (vec_av_set.is_empty ()) |
3939 { | 3938 { |
3940 /* We need to set *pneed_stall here, because later we skip this code | 3939 /* We need to set *pneed_stall here, because later we skip this code |
3941 when ready list is empty. */ | 3940 when ready list is empty. */ |
3942 *pneed_stall = min_need_stall; | 3941 *pneed_stall = min_need_stall; |
3943 return false; | 3942 return false; |
3944 } | 3943 } |
3945 else | 3944 else |
3946 gcc_assert (min_need_stall == 0); | 3945 gcc_assert (min_need_stall == 0); |
3947 | 3946 |
3948 /* Sort the vector. */ | 3947 /* Sort the vector. */ |
3949 VEC_qsort (expr_t, vec_av_set, sel_rank_for_schedule); | 3948 vec_av_set.qsort (sel_rank_for_schedule); |
3950 | 3949 |
3951 if (sched_verbose >= 4) | 3950 if (sched_verbose >= 4) |
3952 { | 3951 { |
3953 sel_print ("Total ready exprs: %d, stalled: %d\n", | 3952 sel_print ("Total ready exprs: %d, stalled: %d\n", |
3954 VEC_length (expr_t, vec_av_set), stalled); | 3953 vec_av_set.length (), stalled); |
3955 sel_print ("Sorted av set (%d): ", VEC_length (expr_t, vec_av_set)); | 3954 sel_print ("Sorted av set (%d): ", vec_av_set.length ()); |
3956 FOR_EACH_VEC_ELT (expr_t, vec_av_set, n, expr) | 3955 FOR_EACH_VEC_ELT (vec_av_set, n, expr) |
3957 dump_expr (expr); | 3956 dump_expr (expr); |
3958 sel_print ("\n"); | 3957 sel_print ("\n"); |
3959 } | 3958 } |
3960 | 3959 |
3961 *pneed_stall = 0; | 3960 *pneed_stall = 0; |
3969 { | 3968 { |
3970 int n; | 3969 int n; |
3971 expr_t expr; | 3970 expr_t expr; |
3972 | 3971 |
3973 /* Allocate and fill the ready list from the sorted vector. */ | 3972 /* Allocate and fill the ready list from the sorted vector. */ |
3974 ready.n_ready = VEC_length (expr_t, vec_av_set); | 3973 ready.n_ready = vec_av_set.length (); |
3975 ready.first = ready.n_ready - 1; | 3974 ready.first = ready.n_ready - 1; |
3976 | 3975 |
3977 gcc_assert (ready.n_ready > 0); | 3976 gcc_assert (ready.n_ready > 0); |
3978 | 3977 |
3979 if (ready.n_ready > max_issue_size) | 3978 if (ready.n_ready > max_issue_size) |
3980 { | 3979 { |
3981 max_issue_size = ready.n_ready; | 3980 max_issue_size = ready.n_ready; |
3982 sched_extend_ready_list (ready.n_ready); | 3981 sched_extend_ready_list (ready.n_ready); |
3983 } | 3982 } |
3984 | 3983 |
3985 FOR_EACH_VEC_ELT (expr_t, vec_av_set, n, expr) | 3984 FOR_EACH_VEC_ELT (vec_av_set, n, expr) |
3986 { | 3985 { |
3987 vinsn_t vi = EXPR_VINSN (expr); | 3986 vinsn_t vi = EXPR_VINSN (expr); |
3988 insn_t insn = VINSN_INSN_RTX (vi); | 3987 insn_t insn = VINSN_INSN_RTX (vi); |
3989 | 3988 |
3990 ready_try[n] = 0; | 3989 ready_try[n] = 0; |
4125 /* Ensure that ready list and vec_av_set are in line with each other, | 4124 /* Ensure that ready list and vec_av_set are in line with each other, |
4126 i.e. vec_av_set[i] == ready_element (&ready, i). */ | 4125 i.e. vec_av_set[i] == ready_element (&ready, i). */ |
4127 if (issue_more && ran_hook) | 4126 if (issue_more && ran_hook) |
4128 { | 4127 { |
4129 int i, j, n; | 4128 int i, j, n; |
4130 rtx *arr = ready.vec; | 4129 rtx_insn **arr = ready.vec; |
4131 expr_t *vec = VEC_address (expr_t, vec_av_set); | 4130 expr_t *vec = vec_av_set.address (); |
4132 | 4131 |
4133 for (i = 0, n = ready.n_ready; i < n; i++) | 4132 for (i = 0, n = ready.n_ready; i < n; i++) |
4134 if (EXPR_INSN_RTX (vec[i]) != arr[i]) | 4133 if (EXPR_INSN_RTX (vec[i]) != arr[i]) |
4135 { | 4134 { |
4136 expr_t tmp; | |
4137 | |
4138 for (j = i; j < n; j++) | 4135 for (j = i; j < n; j++) |
4139 if (EXPR_INSN_RTX (vec[j]) == arr[i]) | 4136 if (EXPR_INSN_RTX (vec[j]) == arr[i]) |
4140 break; | 4137 break; |
4141 gcc_assert (j < n); | 4138 gcc_assert (j < n); |
4142 | 4139 |
4143 tmp = vec[i]; | 4140 std::swap (vec[i], vec[j]); |
4144 vec[i] = vec[j]; | |
4145 vec[j] = tmp; | |
4146 } | 4141 } |
4147 } | 4142 } |
4148 | 4143 |
4149 return issue_more; | 4144 return issue_more; |
4150 } | 4145 } |
4151 | 4146 |
4152 /* Return an EXPR correponding to INDEX element of ready list, if | 4147 /* Return an EXPR corresponding to INDEX element of ready list, if |
4153 FOLLOW_READY_ELEMENT is true (i.e., an expr of | 4148 FOLLOW_READY_ELEMENT is true (i.e., an expr of |
4154 ready_element (&ready, INDEX) will be returned), and to INDEX element of | 4149 ready_element (&ready, INDEX) will be returned), and to INDEX element of |
4155 ready.vec otherwise. */ | 4150 ready.vec otherwise. */ |
4156 static inline expr_t | 4151 static inline expr_t |
4157 find_expr_for_ready (int index, bool follow_ready_element) | 4152 find_expr_for_ready (int index, bool follow_ready_element) |
4159 expr_t expr; | 4154 expr_t expr; |
4160 int real_index; | 4155 int real_index; |
4161 | 4156 |
4162 real_index = follow_ready_element ? ready.first - index : index; | 4157 real_index = follow_ready_element ? ready.first - index : index; |
4163 | 4158 |
4164 expr = VEC_index (expr_t, vec_av_set, real_index); | 4159 expr = vec_av_set[real_index]; |
4165 gcc_assert (ready.vec[real_index] == EXPR_INSN_RTX (expr)); | 4160 gcc_assert (ready.vec[real_index] == EXPR_INSN_RTX (expr)); |
4166 | 4161 |
4167 return expr; | 4162 return expr; |
4168 } | 4163 } |
4169 | 4164 |
4190 insn = ready_element (&ready, i); | 4185 insn = ready_element (&ready, i); |
4191 | 4186 |
4192 if (! have_hook || i == 0) | 4187 if (! have_hook || i == 0) |
4193 r = 0; | 4188 r = 0; |
4194 else | 4189 else |
4195 r = !targetm.sched.first_cycle_multipass_dfa_lookahead_guard (insn); | 4190 r = targetm.sched.first_cycle_multipass_dfa_lookahead_guard (insn, i); |
4196 | 4191 |
4197 gcc_assert (INSN_CODE (insn) >= 0); | 4192 gcc_assert (INSN_CODE (insn) >= 0); |
4198 | 4193 |
4199 /* Only insns with ready_try = 0 can get here | 4194 /* Only insns with ready_try = 0 can get here |
4200 from fill_ready_list. */ | 4195 from fill_ready_list. */ |
4252 /* Call the rest of the hooks after the choice was made. Return | 4247 /* Call the rest of the hooks after the choice was made. Return |
4253 the number of insns that still can be issued given that the current | 4248 the number of insns that still can be issued given that the current |
4254 number is ISSUE_MORE. FENCE and BEST_INSN are the current fence | 4249 number is ISSUE_MORE. FENCE and BEST_INSN are the current fence |
4255 and the insn chosen for scheduling, respectively. */ | 4250 and the insn chosen for scheduling, respectively. */ |
4256 static int | 4251 static int |
4257 invoke_aftermath_hooks (fence_t fence, rtx best_insn, int issue_more) | 4252 invoke_aftermath_hooks (fence_t fence, rtx_insn *best_insn, int issue_more) |
4258 { | 4253 { |
4259 gcc_assert (INSN_P (best_insn)); | 4254 gcc_assert (INSN_P (best_insn)); |
4260 | 4255 |
4261 /* First, call dfa_new_cycle, and then variable_issue, if available. */ | 4256 /* First, call dfa_new_cycle, and then variable_issue, if available. */ |
4262 sel_dfa_new_cycle (best_insn, fence); | 4257 sel_dfa_new_cycle (best_insn, fence); |
4267 issue_more = | 4262 issue_more = |
4268 targetm.sched.variable_issue (sched_dump, sched_verbose, best_insn, | 4263 targetm.sched.variable_issue (sched_dump, sched_verbose, best_insn, |
4269 issue_more); | 4264 issue_more); |
4270 memcpy (FENCE_STATE (fence), curr_state, dfa_state_size); | 4265 memcpy (FENCE_STATE (fence), curr_state, dfa_state_size); |
4271 } | 4266 } |
4272 else if (GET_CODE (PATTERN (best_insn)) != USE | 4267 else if (!DEBUG_INSN_P (best_insn) |
4273 && GET_CODE (PATTERN (best_insn)) != CLOBBER) | 4268 && GET_CODE (PATTERN (best_insn)) != USE |
4269 && GET_CODE (PATTERN (best_insn)) != CLOBBER) | |
4274 issue_more--; | 4270 issue_more--; |
4275 | 4271 |
4276 return issue_more; | 4272 return issue_more; |
4277 } | 4273 } |
4278 | 4274 |
4279 /* Estimate the cost of issuing INSN on DFA state STATE. */ | 4275 /* Estimate the cost of issuing INSN on DFA state STATE. */ |
4280 static int | 4276 static int |
4281 estimate_insn_cost (rtx insn, state_t state) | 4277 estimate_insn_cost (rtx_insn *insn, state_t state) |
4282 { | 4278 { |
4283 static state_t temp = NULL; | 4279 static state_t temp = NULL; |
4284 int cost; | 4280 int cost; |
4285 | 4281 |
4286 if (!temp) | 4282 if (!temp) |
4299 /* Return the cost of issuing EXPR on the FENCE as estimated by DFA. | 4295 /* Return the cost of issuing EXPR on the FENCE as estimated by DFA. |
4300 This function properly handles ASMs, USEs etc. */ | 4296 This function properly handles ASMs, USEs etc. */ |
4301 static int | 4297 static int |
4302 get_expr_cost (expr_t expr, fence_t fence) | 4298 get_expr_cost (expr_t expr, fence_t fence) |
4303 { | 4299 { |
4304 rtx insn = EXPR_INSN_RTX (expr); | 4300 rtx_insn *insn = EXPR_INSN_RTX (expr); |
4305 | 4301 |
4306 if (recog_memoized (insn) < 0) | 4302 if (recog_memoized (insn) < 0) |
4307 { | 4303 { |
4308 if (!FENCE_STARTS_CYCLE_P (fence) | 4304 if (!FENCE_STARTS_CYCLE_P (fence) |
4309 && INSN_ASM_P (insn)) | 4305 && INSN_ASM_P (insn)) |
4497 { | 4493 { |
4498 basic_block candidate_block = NULL; | 4494 basic_block candidate_block = NULL; |
4499 edge e; | 4495 edge e; |
4500 | 4496 |
4501 /* Loop over edges from E1 to E2, inclusive. */ | 4497 /* Loop over edges from E1 to E2, inclusive. */ |
4502 for (e = e1; !lax || e->dest != EXIT_BLOCK_PTR; e = EDGE_SUCC (e->dest, 0)) | 4498 for (e = e1; !lax || e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun); e = |
4499 EDGE_SUCC (e->dest, 0)) | |
4503 { | 4500 { |
4504 if (EDGE_COUNT (e->dest->preds) == 2) | 4501 if (EDGE_COUNT (e->dest->preds) == 2) |
4505 { | 4502 { |
4506 if (candidate_block == NULL) | 4503 if (candidate_block == NULL) |
4507 candidate_block = (EDGE_PRED (e->dest, 0) == e | 4504 candidate_block = (EDGE_PRED (e->dest, 0) == e |
4557 new_bb = sched_split_block (bb, NULL); | 4554 new_bb = sched_split_block (bb, NULL); |
4558 | 4555 |
4559 /* Move note_list from the upper bb. */ | 4556 /* Move note_list from the upper bb. */ |
4560 gcc_assert (BB_NOTE_LIST (new_bb) == NULL_RTX); | 4557 gcc_assert (BB_NOTE_LIST (new_bb) == NULL_RTX); |
4561 BB_NOTE_LIST (new_bb) = BB_NOTE_LIST (bb); | 4558 BB_NOTE_LIST (new_bb) = BB_NOTE_LIST (bb); |
4562 BB_NOTE_LIST (bb) = NULL_RTX; | 4559 BB_NOTE_LIST (bb) = NULL; |
4563 | 4560 |
4564 gcc_assert (e2->dest == bb); | 4561 gcc_assert (e2->dest == bb); |
4565 | 4562 |
4566 /* Skip block for bookkeeping copy when leaving E1->src. */ | 4563 /* Skip block for bookkeeping copy when leaving E1->src. */ |
4567 if (e1->flags & EDGE_FALLTHRU) | 4564 if (e1->flags & EDGE_FALLTHRU) |
4588 insn_t last; | 4585 insn_t last; |
4589 | 4586 |
4590 if (DEBUG_INSN_P (insn) | 4587 if (DEBUG_INSN_P (insn) |
4591 && single_succ_p (new_bb) | 4588 && single_succ_p (new_bb) |
4592 && (succ = single_succ (new_bb)) | 4589 && (succ = single_succ (new_bb)) |
4593 && succ != EXIT_BLOCK_PTR | 4590 && succ != EXIT_BLOCK_PTR_FOR_FN (cfun) |
4594 && DEBUG_INSN_P ((last = sel_bb_end (new_bb)))) | 4591 && DEBUG_INSN_P ((last = sel_bb_end (new_bb)))) |
4595 { | 4592 { |
4596 while (insn != last && (DEBUG_INSN_P (insn) || NOTE_P (insn))) | 4593 while (insn != last && (DEBUG_INSN_P (insn) || NOTE_P (insn))) |
4597 insn = NEXT_INSN (insn); | 4594 insn = NEXT_INSN (insn); |
4598 | 4595 |
4599 if (insn == last) | 4596 if (insn == last) |
4600 { | 4597 { |
4601 sel_global_bb_info_def gbi; | 4598 sel_global_bb_info_def gbi; |
4602 sel_region_bb_info_def rbi; | 4599 sel_region_bb_info_def rbi; |
4603 int i; | |
4604 | 4600 |
4605 if (sched_verbose >= 2) | 4601 if (sched_verbose >= 2) |
4606 sel_print ("Swapping block ids %i and %i\n", | 4602 sel_print ("Swapping block ids %i and %i\n", |
4607 new_bb->index, succ->index); | 4603 new_bb->index, succ->index); |
4608 | 4604 |
4609 i = new_bb->index; | 4605 std::swap (new_bb->index, succ->index); |
4610 new_bb->index = succ->index; | 4606 |
4611 succ->index = i; | 4607 SET_BASIC_BLOCK_FOR_FN (cfun, new_bb->index, new_bb); |
4612 | 4608 SET_BASIC_BLOCK_FOR_FN (cfun, succ->index, succ); |
4613 SET_BASIC_BLOCK (new_bb->index, new_bb); | |
4614 SET_BASIC_BLOCK (succ->index, succ); | |
4615 | 4609 |
4616 memcpy (&gbi, SEL_GLOBAL_BB_INFO (new_bb), sizeof (gbi)); | 4610 memcpy (&gbi, SEL_GLOBAL_BB_INFO (new_bb), sizeof (gbi)); |
4617 memcpy (SEL_GLOBAL_BB_INFO (new_bb), SEL_GLOBAL_BB_INFO (succ), | 4611 memcpy (SEL_GLOBAL_BB_INFO (new_bb), SEL_GLOBAL_BB_INFO (succ), |
4618 sizeof (gbi)); | 4612 sizeof (gbi)); |
4619 memcpy (SEL_GLOBAL_BB_INFO (succ), &gbi, sizeof (gbi)); | 4613 memcpy (SEL_GLOBAL_BB_INFO (succ), &gbi, sizeof (gbi)); |
4621 memcpy (&rbi, SEL_REGION_BB_INFO (new_bb), sizeof (rbi)); | 4615 memcpy (&rbi, SEL_REGION_BB_INFO (new_bb), sizeof (rbi)); |
4622 memcpy (SEL_REGION_BB_INFO (new_bb), SEL_REGION_BB_INFO (succ), | 4616 memcpy (SEL_REGION_BB_INFO (new_bb), SEL_REGION_BB_INFO (succ), |
4623 sizeof (rbi)); | 4617 sizeof (rbi)); |
4624 memcpy (SEL_REGION_BB_INFO (succ), &rbi, sizeof (rbi)); | 4618 memcpy (SEL_REGION_BB_INFO (succ), &rbi, sizeof (rbi)); |
4625 | 4619 |
4626 i = BLOCK_TO_BB (new_bb->index); | 4620 std::swap (BLOCK_TO_BB (new_bb->index), |
4627 BLOCK_TO_BB (new_bb->index) = BLOCK_TO_BB (succ->index); | 4621 BLOCK_TO_BB (succ->index)); |
4628 BLOCK_TO_BB (succ->index) = i; | 4622 |
4629 | 4623 std::swap (CONTAINING_RGN (new_bb->index), |
4630 i = CONTAINING_RGN (new_bb->index); | 4624 CONTAINING_RGN (succ->index)); |
4631 CONTAINING_RGN (new_bb->index) = CONTAINING_RGN (succ->index); | 4625 |
4632 CONTAINING_RGN (succ->index) = i; | 4626 for (int i = 0; i < current_nr_blocks; i++) |
4633 | |
4634 for (i = 0; i < current_nr_blocks; i++) | |
4635 if (BB_TO_BLOCK (i) == succ->index) | 4627 if (BB_TO_BLOCK (i) == succ->index) |
4636 BB_TO_BLOCK (i) = new_bb->index; | 4628 BB_TO_BLOCK (i) = new_bb->index; |
4637 else if (BB_TO_BLOCK (i) == new_bb->index) | 4629 else if (BB_TO_BLOCK (i) == new_bb->index) |
4638 BB_TO_BLOCK (i) = succ->index; | 4630 BB_TO_BLOCK (i) = succ->index; |
4639 | 4631 |
4654 if (sched_verbose >= 4) | 4646 if (sched_verbose >= 4) |
4655 sel_print ("Swapping code labels %i and %i\n", | 4647 sel_print ("Swapping code labels %i and %i\n", |
4656 CODE_LABEL_NUMBER (BB_HEAD (new_bb)), | 4648 CODE_LABEL_NUMBER (BB_HEAD (new_bb)), |
4657 CODE_LABEL_NUMBER (BB_HEAD (succ))); | 4649 CODE_LABEL_NUMBER (BB_HEAD (succ))); |
4658 | 4650 |
4659 i = CODE_LABEL_NUMBER (BB_HEAD (new_bb)); | 4651 std::swap (CODE_LABEL_NUMBER (BB_HEAD (new_bb)), |
4660 CODE_LABEL_NUMBER (BB_HEAD (new_bb)) | 4652 CODE_LABEL_NUMBER (BB_HEAD (succ))); |
4661 = CODE_LABEL_NUMBER (BB_HEAD (succ)); | |
4662 CODE_LABEL_NUMBER (BB_HEAD (succ)) = i; | |
4663 } | 4653 } |
4664 } | 4654 } |
4665 } | 4655 } |
4666 | 4656 |
4667 return bb; | 4657 return bb; |
4668 } | 4658 } |
4669 | 4659 |
4670 /* Return insn after which we must insert bookkeeping code for path(s) incoming | 4660 /* Return insn after which we must insert bookkeeping code for path(s) incoming |
4671 into E2->dest, except from E1->src. */ | 4661 into E2->dest, except from E1->src. If the returned insn immediately |
4662 precedes a fence, assign that fence to *FENCE_TO_REWIND. */ | |
4672 static insn_t | 4663 static insn_t |
4673 find_place_for_bookkeeping (edge e1, edge e2) | 4664 find_place_for_bookkeeping (edge e1, edge e2, fence_t *fence_to_rewind) |
4674 { | 4665 { |
4675 insn_t place_to_insert; | 4666 insn_t place_to_insert; |
4676 /* Find a basic block that can hold bookkeeping. If it can be found, do not | 4667 /* Find a basic block that can hold bookkeeping. If it can be found, do not |
4677 create new basic block, but insert bookkeeping there. */ | 4668 create new basic block, but insert bookkeeping there. */ |
4678 basic_block book_block = find_block_for_bookkeeping (e1, e2, FALSE); | 4669 basic_block book_block = find_block_for_bookkeeping (e1, e2, FALSE); |
4685 bookkeeping, this causes scheduling differences between debug | 4676 bookkeeping, this causes scheduling differences between debug |
4686 and non-debug compilations, for the block would have been | 4677 and non-debug compilations, for the block would have been |
4687 removed already. */ | 4678 removed already. */ |
4688 if (DEBUG_INSN_P (place_to_insert)) | 4679 if (DEBUG_INSN_P (place_to_insert)) |
4689 { | 4680 { |
4690 rtx insn = sel_bb_head (book_block); | 4681 rtx_insn *insn = sel_bb_head (book_block); |
4691 | 4682 |
4692 while (insn != place_to_insert && | 4683 while (insn != place_to_insert && |
4693 (DEBUG_INSN_P (insn) || NOTE_P (insn))) | 4684 (DEBUG_INSN_P (insn) || NOTE_P (insn))) |
4694 insn = NEXT_INSN (insn); | 4685 insn = NEXT_INSN (insn); |
4695 | 4686 |
4710 { | 4701 { |
4711 if (sched_verbose >= 9) | 4702 if (sched_verbose >= 9) |
4712 sel_print ("Pre-existing bookkeeping block is %i\n", book_block->index); | 4703 sel_print ("Pre-existing bookkeeping block is %i\n", book_block->index); |
4713 } | 4704 } |
4714 | 4705 |
4715 /* If basic block ends with a jump, insert bookkeeping code right before it. */ | 4706 *fence_to_rewind = NULL; |
4707 /* If basic block ends with a jump, insert bookkeeping code right before it. | |
4708 Notice if we are crossing a fence when taking PREV_INSN. */ | |
4716 if (INSN_P (place_to_insert) && control_flow_insn_p (place_to_insert)) | 4709 if (INSN_P (place_to_insert) && control_flow_insn_p (place_to_insert)) |
4717 place_to_insert = PREV_INSN (place_to_insert); | 4710 { |
4711 *fence_to_rewind = flist_lookup (fences, place_to_insert); | |
4712 place_to_insert = PREV_INSN (place_to_insert); | |
4713 } | |
4718 | 4714 |
4719 return place_to_insert; | 4715 return place_to_insert; |
4720 } | 4716 } |
4721 | 4717 |
4722 /* Find a proper seqno for bookkeeing insn inserted at PLACE_TO_INSERT | 4718 /* Find a proper seqno for bookkeeing insn inserted at PLACE_TO_INSERT |
4723 for JOIN_POINT. */ | 4719 for JOIN_POINT. */ |
4724 static int | 4720 static int |
4725 find_seqno_for_bookkeeping (insn_t place_to_insert, insn_t join_point) | 4721 find_seqno_for_bookkeeping (insn_t place_to_insert, insn_t join_point) |
4726 { | 4722 { |
4727 int seqno; | 4723 int seqno; |
4728 rtx next; | |
4729 | 4724 |
4730 /* Check if we are about to insert bookkeeping copy before a jump, and use | 4725 /* Check if we are about to insert bookkeeping copy before a jump, and use |
4731 jump's seqno for the copy; otherwise, use JOIN_POINT's seqno. */ | 4726 jump's seqno for the copy; otherwise, use JOIN_POINT's seqno. */ |
4732 next = NEXT_INSN (place_to_insert); | 4727 rtx_insn *next = NEXT_INSN (place_to_insert); |
4733 if (INSN_P (next) | 4728 if (INSN_P (next) |
4734 && JUMP_P (next) | 4729 && JUMP_P (next) |
4735 && BLOCK_FOR_INSN (next) == BLOCK_FOR_INSN (place_to_insert)) | 4730 && BLOCK_FOR_INSN (next) == BLOCK_FOR_INSN (place_to_insert)) |
4736 { | 4731 { |
4737 gcc_assert (INSN_SCHED_TIMES (next) == 0); | 4732 gcc_assert (INSN_SCHED_TIMES (next) == 0); |
4762 /* Insert bookkeeping copy of C_EXPS's insn after PLACE_TO_INSERT, assigning | 4757 /* Insert bookkeeping copy of C_EXPS's insn after PLACE_TO_INSERT, assigning |
4763 NEW_SEQNO to it. Return created insn. */ | 4758 NEW_SEQNO to it. Return created insn. */ |
4764 static insn_t | 4759 static insn_t |
4765 emit_bookkeeping_insn (insn_t place_to_insert, expr_t c_expr, int new_seqno) | 4760 emit_bookkeeping_insn (insn_t place_to_insert, expr_t c_expr, int new_seqno) |
4766 { | 4761 { |
4767 rtx new_insn_rtx = create_copy_of_insn_rtx (EXPR_INSN_RTX (c_expr)); | 4762 rtx_insn *new_insn_rtx = create_copy_of_insn_rtx (EXPR_INSN_RTX (c_expr)); |
4768 | 4763 |
4769 vinsn_t new_vinsn | 4764 vinsn_t new_vinsn |
4770 = create_vinsn_from_insn_rtx (new_insn_rtx, | 4765 = create_vinsn_from_insn_rtx (new_insn_rtx, |
4771 VINSN_UNIQUE_P (EXPR_VINSN (c_expr))); | 4766 VINSN_UNIQUE_P (EXPR_VINSN (c_expr))); |
4772 | 4767 |
4787 generate_bookkeeping_insn (expr_t c_expr, edge e1, edge e2) | 4782 generate_bookkeeping_insn (expr_t c_expr, edge e1, edge e2) |
4788 { | 4783 { |
4789 insn_t join_point, place_to_insert, new_insn; | 4784 insn_t join_point, place_to_insert, new_insn; |
4790 int new_seqno; | 4785 int new_seqno; |
4791 bool need_to_exchange_data_sets; | 4786 bool need_to_exchange_data_sets; |
4787 fence_t fence_to_rewind; | |
4792 | 4788 |
4793 if (sched_verbose >= 4) | 4789 if (sched_verbose >= 4) |
4794 sel_print ("Generating bookkeeping insn (%d->%d)\n", e1->src->index, | 4790 sel_print ("Generating bookkeeping insn (%d->%d)\n", e1->src->index, |
4795 e2->dest->index); | 4791 e2->dest->index); |
4796 | 4792 |
4797 join_point = sel_bb_head (e2->dest); | 4793 join_point = sel_bb_head (e2->dest); |
4798 place_to_insert = find_place_for_bookkeeping (e1, e2); | 4794 place_to_insert = find_place_for_bookkeeping (e1, e2, &fence_to_rewind); |
4799 if (!place_to_insert) | |
4800 return NULL; | |
4801 new_seqno = find_seqno_for_bookkeeping (place_to_insert, join_point); | 4795 new_seqno = find_seqno_for_bookkeeping (place_to_insert, join_point); |
4802 need_to_exchange_data_sets | 4796 need_to_exchange_data_sets |
4803 = sel_bb_empty_p (BLOCK_FOR_INSN (place_to_insert)); | 4797 = sel_bb_empty_p (BLOCK_FOR_INSN (place_to_insert)); |
4804 | 4798 |
4805 new_insn = emit_bookkeeping_insn (place_to_insert, c_expr, new_seqno); | 4799 new_insn = emit_bookkeeping_insn (place_to_insert, c_expr, new_seqno); |
4800 | |
4801 if (fence_to_rewind) | |
4802 FENCE_INSN (fence_to_rewind) = new_insn; | |
4806 | 4803 |
4807 /* When inserting bookkeeping insn in new block, av sets should be | 4804 /* When inserting bookkeeping insn in new block, av sets should be |
4808 following: old basic block (that now holds bookkeeping) data sets are | 4805 following: old basic block (that now holds bookkeeping) data sets are |
4809 the same as was before generation of bookkeeping, and new basic block | 4806 the same as was before generation of bookkeeping, and new basic block |
4810 (that now hold all other insns of old basic block) data sets are | 4807 (that now hold all other insns of old basic block) data sets are |
4840 if (!control_flow_insn_p (EXPR_INSN_RTX (expr)) | 4837 if (!control_flow_insn_p (EXPR_INSN_RTX (expr)) |
4841 && (!bookkeeping_p || VINSN_UNIQUE_P (EXPR_VINSN (expr))) | 4838 && (!bookkeeping_p || VINSN_UNIQUE_P (EXPR_VINSN (expr))) |
4842 && (EXPR_SPEC (expr) | 4839 && (EXPR_SPEC (expr) |
4843 || !EXPR_ORIG_BB_INDEX (expr) | 4840 || !EXPR_ORIG_BB_INDEX (expr) |
4844 || !dominated_by_p (CDI_DOMINATORS, | 4841 || !dominated_by_p (CDI_DOMINATORS, |
4845 BASIC_BLOCK (EXPR_ORIG_BB_INDEX (expr)), | 4842 BASIC_BLOCK_FOR_FN (cfun, |
4843 EXPR_ORIG_BB_INDEX (expr)), | |
4846 BLOCK_FOR_INSN (FENCE_INSN (fence))))) | 4844 BLOCK_FOR_INSN (FENCE_INSN (fence))))) |
4847 { | 4845 { |
4848 if (sched_verbose >= 4) | 4846 if (sched_verbose >= 4) |
4849 sel_print ("Expr %d removed because it would need bookkeeping, which " | 4847 sel_print ("Expr %d removed because it would need bookkeeping, which " |
4850 "cannot be created\n", INSN_UID (EXPR_INSN_RTX (expr))); | 4848 "cannot be created\n", INSN_UID (EXPR_INSN_RTX (expr))); |
4883 (p8) mov [r14]=r23 | 4881 (p8) mov [r14]=r23 |
4884 NOTE BASIC BLOCK: | 4882 NOTE BASIC BLOCK: |
4885 ... | 4883 ... |
4886 */ | 4884 */ |
4887 static void | 4885 static void |
4888 move_cond_jump (rtx insn, bnd_t bnd) | 4886 move_cond_jump (rtx_insn *insn, bnd_t bnd) |
4889 { | 4887 { |
4890 edge ft_edge; | 4888 edge ft_edge; |
4891 basic_block block_from, block_next, block_new, block_bnd, bb; | 4889 basic_block block_from, block_next, block_new, block_bnd, bb; |
4892 rtx next, prev, link, head; | 4890 rtx_insn *next, *prev, *link, *head; |
4893 | 4891 |
4894 block_from = BLOCK_FOR_INSN (insn); | 4892 block_from = BLOCK_FOR_INSN (insn); |
4895 block_bnd = BLOCK_FOR_INSN (BND_TO (bnd)); | 4893 block_bnd = BLOCK_FOR_INSN (BND_TO (bnd)); |
4896 prev = BND_TO (bnd); | 4894 prev = BND_TO (bnd); |
4897 | 4895 |
4898 #ifdef ENABLE_CHECKING | |
4899 /* Moving of jump should not cross any other jumps or beginnings of new | 4896 /* Moving of jump should not cross any other jumps or beginnings of new |
4900 basic blocks. The only exception is when we move a jump through | 4897 basic blocks. The only exception is when we move a jump through |
4901 mutually exclusive insns along fallthru edges. */ | 4898 mutually exclusive insns along fallthru edges. */ |
4902 if (block_from != block_bnd) | 4899 if (flag_checking && block_from != block_bnd) |
4903 { | 4900 { |
4904 bb = block_from; | 4901 bb = block_from; |
4905 for (link = PREV_INSN (insn); link != PREV_INSN (prev); | 4902 for (link = PREV_INSN (insn); link != PREV_INSN (prev); |
4906 link = PREV_INSN (link)) | 4903 link = PREV_INSN (link)) |
4907 { | 4904 { |
4912 gcc_assert (single_pred (bb) == BLOCK_FOR_INSN (link)); | 4909 gcc_assert (single_pred (bb) == BLOCK_FOR_INSN (link)); |
4913 bb = BLOCK_FOR_INSN (link); | 4910 bb = BLOCK_FOR_INSN (link); |
4914 } | 4911 } |
4915 } | 4912 } |
4916 } | 4913 } |
4917 #endif | |
4918 | 4914 |
4919 /* Jump is moved to the boundary. */ | 4915 /* Jump is moved to the boundary. */ |
4920 next = PREV_INSN (insn); | 4916 next = PREV_INSN (insn); |
4921 BND_TO (bnd) = insn; | 4917 BND_TO (bnd) = insn; |
4922 | 4918 |
4934 /* Move all instructions except INSN to BLOCK_NEW. */ | 4930 /* Move all instructions except INSN to BLOCK_NEW. */ |
4935 bb = block_bnd; | 4931 bb = block_bnd; |
4936 head = BB_HEAD (block_new); | 4932 head = BB_HEAD (block_new); |
4937 while (bb != block_from->next_bb) | 4933 while (bb != block_from->next_bb) |
4938 { | 4934 { |
4939 rtx from, to; | 4935 rtx_insn *from, *to; |
4940 from = bb == block_bnd ? prev : sel_bb_head (bb); | 4936 from = bb == block_bnd ? prev : sel_bb_head (bb); |
4941 to = bb == block_from ? next : sel_bb_end (bb); | 4937 to = bb == block_from ? next : sel_bb_end (bb); |
4942 | 4938 |
4943 /* The jump being moved can be the first insn in the block. | 4939 /* The jump being moved can be the first insn in the block. |
4944 In this case we don't have to move anything in this block. */ | 4940 In this case we don't have to move anything in this block. */ |
4986 remove_temp_moveop_nops (bool full_tidying) | 4982 remove_temp_moveop_nops (bool full_tidying) |
4987 { | 4983 { |
4988 int i; | 4984 int i; |
4989 insn_t insn; | 4985 insn_t insn; |
4990 | 4986 |
4991 FOR_EACH_VEC_ELT (insn_t, vec_temp_moveop_nops, i, insn) | 4987 FOR_EACH_VEC_ELT (vec_temp_moveop_nops, i, insn) |
4992 { | 4988 { |
4993 gcc_assert (INSN_NOP_P (insn)); | 4989 gcc_assert (INSN_NOP_P (insn)); |
4994 return_nop_to_pool (insn, full_tidying); | 4990 return_nop_to_pool (insn, full_tidying); |
4995 } | 4991 } |
4996 | 4992 |
4997 /* Empty the vector. */ | 4993 /* Empty the vector. */ |
4998 if (VEC_length (insn_t, vec_temp_moveop_nops) > 0) | 4994 if (vec_temp_moveop_nops.length () > 0) |
4999 VEC_block_remove (insn_t, vec_temp_moveop_nops, 0, | 4995 vec_temp_moveop_nops.block_remove (0, vec_temp_moveop_nops.length ()); |
5000 VEC_length (insn_t, vec_temp_moveop_nops)); | |
5001 } | 4996 } |
5002 | 4997 |
5003 /* Records the maximal UID before moving up an instruction. Used for | 4998 /* Records the maximal UID before moving up an instruction. Used for |
5004 distinguishing between bookkeeping copies and original insns. */ | 4999 distinguishing between bookkeeping copies and original insns. */ |
5005 static int max_uid_before_move_op = 0; | 5000 static int max_uid_before_move_op = 0; |
5146 | 5141 |
5147 /* Move nop to previous block. */ | 5142 /* Move nop to previous block. */ |
5148 static void ATTRIBUTE_UNUSED | 5143 static void ATTRIBUTE_UNUSED |
5149 move_nop_to_previous_block (insn_t nop, basic_block prev_bb) | 5144 move_nop_to_previous_block (insn_t nop, basic_block prev_bb) |
5150 { | 5145 { |
5151 insn_t prev_insn, next_insn, note; | 5146 insn_t prev_insn, next_insn; |
5152 | 5147 |
5153 gcc_assert (sel_bb_head_p (nop) | 5148 gcc_assert (sel_bb_head_p (nop) |
5154 && prev_bb == BLOCK_FOR_INSN (nop)->prev_bb); | 5149 && prev_bb == BLOCK_FOR_INSN (nop)->prev_bb); |
5155 note = bb_note (BLOCK_FOR_INSN (nop)); | 5150 rtx_note *note = bb_note (BLOCK_FOR_INSN (nop)); |
5156 prev_insn = sel_bb_end (prev_bb); | 5151 prev_insn = sel_bb_end (prev_bb); |
5157 next_insn = NEXT_INSN (nop); | 5152 next_insn = NEXT_INSN (nop); |
5158 gcc_assert (prev_insn != NULL_RTX | 5153 gcc_assert (prev_insn != NULL_RTX |
5159 && PREV_INSN (note) == prev_insn); | 5154 && PREV_INSN (note) == prev_insn); |
5160 | 5155 |
5161 NEXT_INSN (prev_insn) = nop; | 5156 SET_NEXT_INSN (prev_insn) = nop; |
5162 PREV_INSN (nop) = prev_insn; | 5157 SET_PREV_INSN (nop) = prev_insn; |
5163 | 5158 |
5164 PREV_INSN (note) = nop; | 5159 SET_PREV_INSN (note) = nop; |
5165 NEXT_INSN (note) = next_insn; | 5160 SET_NEXT_INSN (note) = next_insn; |
5166 | 5161 |
5167 NEXT_INSN (nop) = note; | 5162 SET_NEXT_INSN (nop) = note; |
5168 PREV_INSN (next_insn) = note; | 5163 SET_PREV_INSN (next_insn) = note; |
5169 | 5164 |
5170 BB_END (prev_bb) = nop; | 5165 BB_END (prev_bb) = nop; |
5171 BLOCK_FOR_INSN (nop) = prev_bb; | 5166 BLOCK_FOR_INSN (nop) = prev_bb; |
5172 } | 5167 } |
5173 | 5168 |
5328 bool asm_p; | 5323 bool asm_p; |
5329 | 5324 |
5330 /* First, reflect that something is scheduled on this fence. */ | 5325 /* First, reflect that something is scheduled on this fence. */ |
5331 asm_p = advance_state_on_fence (fence, insn); | 5326 asm_p = advance_state_on_fence (fence, insn); |
5332 FENCE_LAST_SCHEDULED_INSN (fence) = insn; | 5327 FENCE_LAST_SCHEDULED_INSN (fence) = insn; |
5333 VEC_safe_push (rtx, gc, FENCE_EXECUTING_INSNS (fence), insn); | 5328 vec_safe_push (FENCE_EXECUTING_INSNS (fence), insn); |
5334 if (SCHED_GROUP_P (insn)) | 5329 if (SCHED_GROUP_P (insn)) |
5335 { | 5330 { |
5336 FENCE_SCHED_NEXT (fence) = INSN_SCHED_NEXT (insn); | 5331 FENCE_SCHED_NEXT (fence) = INSN_SCHED_NEXT (insn); |
5337 SCHED_GROUP_P (insn) = 0; | 5332 SCHED_GROUP_P (insn) = 0; |
5338 } | 5333 } |
5339 else | 5334 else |
5340 FENCE_SCHED_NEXT (fence) = NULL_RTX; | 5335 FENCE_SCHED_NEXT (fence) = NULL; |
5341 if (INSN_UID (insn) < FENCE_READY_TICKS_SIZE (fence)) | 5336 if (INSN_UID (insn) < FENCE_READY_TICKS_SIZE (fence)) |
5342 FENCE_READY_TICKS (fence) [INSN_UID (insn)] = 0; | 5337 FENCE_READY_TICKS (fence) [INSN_UID (insn)] = 0; |
5343 | 5338 |
5344 /* Set instruction scheduling info. This will be used in bundling, | 5339 /* Set instruction scheduling info. This will be used in bundling, |
5345 pipelining, tick computations etc. */ | 5340 pipelining, tick computations etc. */ |
5520 /* Do while we can add any operation to the current group. */ | 5515 /* Do while we can add any operation to the current group. */ |
5521 do | 5516 do |
5522 { | 5517 { |
5523 blist_t *bnds_tailp1, *bndsp; | 5518 blist_t *bnds_tailp1, *bndsp; |
5524 expr_t expr_vliw; | 5519 expr_t expr_vliw; |
5525 int need_stall; | 5520 int need_stall = false; |
5526 int was_stall = 0, scheduled_insns = 0; | 5521 int was_stall = 0, scheduled_insns = 0; |
5527 int max_insns = pipelining_p ? issue_rate : 2 * issue_rate; | 5522 int max_insns = pipelining_p ? issue_rate : 2 * issue_rate; |
5528 int max_stall = pipelining_p ? 1 : 3; | 5523 int max_stall = pipelining_p ? 1 : 3; |
5529 bool last_insn_was_debug = false; | 5524 bool last_insn_was_debug = false; |
5530 bool was_debug_bb_end_p = false; | 5525 bool was_debug_bb_end_p = false; |
5669 update_and_record_unavailable_insns (basic_block book_block) | 5664 update_and_record_unavailable_insns (basic_block book_block) |
5670 { | 5665 { |
5671 av_set_iterator i; | 5666 av_set_iterator i; |
5672 av_set_t old_av_set = NULL; | 5667 av_set_t old_av_set = NULL; |
5673 expr_t cur_expr; | 5668 expr_t cur_expr; |
5674 rtx bb_end = sel_bb_end (book_block); | 5669 rtx_insn *bb_end = sel_bb_end (book_block); |
5675 | 5670 |
5676 /* First, get correct liveness in the bookkeeping block. The problem is | 5671 /* First, get correct liveness in the bookkeeping block. The problem is |
5677 the range between the bookeeping insn and the end of block. */ | 5672 the range between the bookeeping insn and the end of block. */ |
5678 update_liveness_on_insn (bb_end); | 5673 update_liveness_on_insn (bb_end); |
5679 if (control_flow_insn_p (bb_end)) | 5674 if (control_flow_insn_p (bb_end)) |
5698 /* In this case, we can just turn off the E_T_A bit, but we can't | 5693 /* In this case, we can just turn off the E_T_A bit, but we can't |
5699 represent this information with the current vector. */ | 5694 represent this information with the current vector. */ |
5700 || EXPR_TARGET_AVAILABLE (new_expr) | 5695 || EXPR_TARGET_AVAILABLE (new_expr) |
5701 != EXPR_TARGET_AVAILABLE (cur_expr)) | 5696 != EXPR_TARGET_AVAILABLE (cur_expr)) |
5702 /* Unfortunately, the below code could be also fired up on | 5697 /* Unfortunately, the below code could be also fired up on |
5703 separable insns. | 5698 separable insns, e.g. when moving insns through the new |
5704 FIXME: add an example of how this could happen. */ | 5699 speculation check as in PR 53701. */ |
5705 vinsn_vec_add (&vec_bookkeeping_blocked_vinsns, cur_expr); | 5700 vinsn_vec_add (&vec_bookkeeping_blocked_vinsns, cur_expr); |
5706 } | 5701 } |
5707 | 5702 |
5708 av_set_clear (&old_av_set); | 5703 av_set_clear (&old_av_set); |
5709 } | 5704 } |
5810 } | 5805 } |
5811 | 5806 |
5812 /* Track bookkeeping copies created, insns scheduled, and blocks for | 5807 /* Track bookkeeping copies created, insns scheduled, and blocks for |
5813 rescheduling when INSN is found by move_op. */ | 5808 rescheduling when INSN is found by move_op. */ |
5814 static void | 5809 static void |
5815 track_scheduled_insns_and_blocks (rtx insn) | 5810 track_scheduled_insns_and_blocks (rtx_insn *insn) |
5816 { | 5811 { |
5817 /* Even if this insn can be a copy that will be removed during current move_op, | 5812 /* Even if this insn can be a copy that will be removed during current move_op, |
5818 we still need to count it as an originator. */ | 5813 we still need to count it as an originator. */ |
5819 bitmap_set_bit (current_originators, INSN_UID (insn)); | 5814 bitmap_set_bit (current_originators, INSN_UID (insn)); |
5820 | 5815 |
5837 } | 5832 } |
5838 | 5833 |
5839 /* Emit a register-register copy for INSN if needed. Return true if | 5834 /* Emit a register-register copy for INSN if needed. Return true if |
5840 emitted one. PARAMS is the move_op static parameters. */ | 5835 emitted one. PARAMS is the move_op static parameters. */ |
5841 static bool | 5836 static bool |
5842 maybe_emit_renaming_copy (rtx insn, | 5837 maybe_emit_renaming_copy (rtx_insn *insn, |
5843 moveop_static_params_p params) | 5838 moveop_static_params_p params) |
5844 { | 5839 { |
5845 bool insn_emitted = false; | 5840 bool insn_emitted = false; |
5846 rtx cur_reg; | 5841 rtx cur_reg; |
5847 | 5842 |
5877 | 5872 |
5878 /* Emit a speculative check for INSN speculated as EXPR if needed. | 5873 /* Emit a speculative check for INSN speculated as EXPR if needed. |
5879 Return true if we've emitted one. PARAMS is the move_op static | 5874 Return true if we've emitted one. PARAMS is the move_op static |
5880 parameters. */ | 5875 parameters. */ |
5881 static bool | 5876 static bool |
5882 maybe_emit_speculative_check (rtx insn, expr_t expr, | 5877 maybe_emit_speculative_check (rtx_insn *insn, expr_t expr, |
5883 moveop_static_params_p params) | 5878 moveop_static_params_p params) |
5884 { | 5879 { |
5885 bool insn_emitted = false; | 5880 bool insn_emitted = false; |
5886 insn_t x; | 5881 insn_t x; |
5887 ds_t check_ds; | 5882 ds_t check_ds; |
5906 | 5901 |
5907 /* Handle transformations that leave an insn in place of original | 5902 /* Handle transformations that leave an insn in place of original |
5908 insn such as renaming/speculation. Return true if one of such | 5903 insn such as renaming/speculation. Return true if one of such |
5909 transformations actually happened, and we have emitted this insn. */ | 5904 transformations actually happened, and we have emitted this insn. */ |
5910 static bool | 5905 static bool |
5911 handle_emitting_transformations (rtx insn, expr_t expr, | 5906 handle_emitting_transformations (rtx_insn *insn, expr_t expr, |
5912 moveop_static_params_p params) | 5907 moveop_static_params_p params) |
5913 { | 5908 { |
5914 bool insn_emitted = false; | 5909 bool insn_emitted = false; |
5915 | 5910 |
5916 insn_emitted = maybe_emit_renaming_copy (insn, params); | 5911 insn_emitted = maybe_emit_renaming_copy (insn, params); |
5922 /* If INSN is the only insn in the basic block (not counting JUMP, | 5917 /* If INSN is the only insn in the basic block (not counting JUMP, |
5923 which may be a jump to next insn, and DEBUG_INSNs), we want to | 5918 which may be a jump to next insn, and DEBUG_INSNs), we want to |
5924 leave a NOP there till the return to fill_insns. */ | 5919 leave a NOP there till the return to fill_insns. */ |
5925 | 5920 |
5926 static bool | 5921 static bool |
5927 need_nop_to_preserve_insn_bb (rtx insn) | 5922 need_nop_to_preserve_insn_bb (rtx_insn *insn) |
5928 { | 5923 { |
5929 insn_t bb_head, bb_end, bb_next, in_next; | 5924 insn_t bb_head, bb_end, bb_next, in_next; |
5930 basic_block bb = BLOCK_FOR_INSN (insn); | 5925 basic_block bb = BLOCK_FOR_INSN (insn); |
5931 | 5926 |
5932 bb_head = sel_bb_head (bb); | 5927 bb_head = sel_bb_head (bb); |
5965 } | 5960 } |
5966 | 5961 |
5967 /* Remove INSN from stream. When ONLY_DISCONNECT is true, its data | 5962 /* Remove INSN from stream. When ONLY_DISCONNECT is true, its data |
5968 is not removed but reused when INSN is re-emitted. */ | 5963 is not removed but reused when INSN is re-emitted. */ |
5969 static void | 5964 static void |
5970 remove_insn_from_stream (rtx insn, bool only_disconnect) | 5965 remove_insn_from_stream (rtx_insn *insn, bool only_disconnect) |
5971 { | 5966 { |
5972 /* If there's only one insn in the BB, make sure that a nop is | 5967 /* If there's only one insn in the BB, make sure that a nop is |
5973 inserted into it, so the basic block won't disappear when we'll | 5968 inserted into it, so the basic block won't disappear when we'll |
5974 delete INSN below with sel_remove_insn. It should also survive | 5969 delete INSN below with sel_remove_insn. It should also survive |
5975 till the return to fill_insns. */ | 5970 till the return to fill_insns. */ |
5976 if (need_nop_to_preserve_insn_bb (insn)) | 5971 if (need_nop_to_preserve_insn_bb (insn)) |
5977 { | 5972 { |
5978 insn_t nop = get_nop_from_pool (insn); | 5973 insn_t nop = get_nop_from_pool (insn); |
5979 gcc_assert (INSN_NOP_P (nop)); | 5974 gcc_assert (INSN_NOP_P (nop)); |
5980 VEC_safe_push (insn_t, heap, vec_temp_moveop_nops, nop); | 5975 vec_temp_moveop_nops.safe_push (nop); |
5981 } | 5976 } |
5982 | 5977 |
5983 sel_remove_insn (insn, only_disconnect, false); | 5978 sel_remove_insn (insn, only_disconnect, false); |
5984 } | 5979 } |
5985 | 5980 |
5990 static void | 5985 static void |
5991 move_op_orig_expr_found (insn_t insn, expr_t expr, | 5986 move_op_orig_expr_found (insn_t insn, expr_t expr, |
5992 cmpd_local_params_p lparams ATTRIBUTE_UNUSED, | 5987 cmpd_local_params_p lparams ATTRIBUTE_UNUSED, |
5993 void *static_params) | 5988 void *static_params) |
5994 { | 5989 { |
5995 bool only_disconnect, insn_emitted; | 5990 bool only_disconnect; |
5996 moveop_static_params_p params = (moveop_static_params_p) static_params; | 5991 moveop_static_params_p params = (moveop_static_params_p) static_params; |
5997 | 5992 |
5998 copy_expr_onside (params->c_expr, INSN_EXPR (insn)); | 5993 copy_expr_onside (params->c_expr, INSN_EXPR (insn)); |
5999 track_scheduled_insns_and_blocks (insn); | 5994 track_scheduled_insns_and_blocks (insn); |
6000 insn_emitted = handle_emitting_transformations (insn, expr, params); | 5995 handle_emitting_transformations (insn, expr, params); |
6001 only_disconnect = (params->uid == INSN_UID (insn) | 5996 only_disconnect = params->uid == INSN_UID (insn); |
6002 && ! insn_emitted && ! EXPR_WAS_CHANGED (expr)); | |
6003 | 5997 |
6004 /* Mark that we've disconnected an insn. */ | 5998 /* Mark that we've disconnected an insn. */ |
6005 if (only_disconnect) | 5999 if (only_disconnect) |
6006 params->uid = -1; | 6000 params->uid = -1; |
6007 remove_insn_from_stream (insn, only_disconnect); | 6001 remove_insn_from_stream (insn, only_disconnect); |
6211 move_op_orig_expr_not_found (insn_t insn, av_set_t orig_ops ATTRIBUTE_UNUSED, | 6205 move_op_orig_expr_not_found (insn_t insn, av_set_t orig_ops ATTRIBUTE_UNUSED, |
6212 void *static_params) | 6206 void *static_params) |
6213 { | 6207 { |
6214 moveop_static_params_p sparams = (moveop_static_params_p) static_params; | 6208 moveop_static_params_p sparams = (moveop_static_params_p) static_params; |
6215 | 6209 |
6216 #ifdef ENABLE_CHECKING | |
6217 sparams->failed_insn = insn; | 6210 sparams->failed_insn = insn; |
6218 #endif | |
6219 | 6211 |
6220 /* If we're scheduling separate expr, in order to generate correct code | 6212 /* If we're scheduling separate expr, in order to generate correct code |
6221 we need to stop the search at bookkeeping code generated with the | 6213 we need to stop the search at bookkeeping code generated with the |
6222 same destination register or memory. */ | 6214 same destination register or memory. */ |
6223 if (lhs_of_insn_equals_to_dest_p (insn, sparams->dest)) | 6215 if (lhs_of_insn_equals_to_dest_p (insn, sparams->dest)) |
6314 code_motion_process_successors (insn_t insn, av_set_t orig_ops, | 6306 code_motion_process_successors (insn_t insn, av_set_t orig_ops, |
6315 ilist_t path, void *static_params) | 6307 ilist_t path, void *static_params) |
6316 { | 6308 { |
6317 int res = 0; | 6309 int res = 0; |
6318 succ_iterator succ_i; | 6310 succ_iterator succ_i; |
6319 rtx succ; | 6311 insn_t succ; |
6320 basic_block bb; | 6312 basic_block bb; |
6321 int old_index; | 6313 int old_index; |
6322 unsigned old_succs; | 6314 unsigned old_succs; |
6323 | 6315 |
6324 struct cmpd_local_params lparams; | 6316 struct cmpd_local_params lparams; |
6364 res = b; | 6356 res = b; |
6365 else if (b == -1 && res != 1) | 6357 else if (b == -1 && res != 1) |
6366 res = b; | 6358 res = b; |
6367 | 6359 |
6368 /* We have simplified the control flow below this point. In this case, | 6360 /* We have simplified the control flow below this point. In this case, |
6369 the iterator becomes invalid. We need to try again. */ | 6361 the iterator becomes invalid. We need to try again. |
6362 If we have removed the insn itself, it could be only an | |
6363 unconditional jump. Thus, do not rescan but break immediately -- | |
6364 we have already visited the only successor block. */ | |
6365 if (!BLOCK_FOR_INSN (insn)) | |
6366 { | |
6367 if (sched_verbose >= 6) | |
6368 sel_print ("Not doing rescan: already visited the only successor" | |
6369 " of block %d\n", old_index); | |
6370 break; | |
6371 } | |
6370 if (BLOCK_FOR_INSN (insn)->index != old_index | 6372 if (BLOCK_FOR_INSN (insn)->index != old_index |
6371 || EDGE_COUNT (bb->succs) != old_succs) | 6373 || EDGE_COUNT (bb->succs) != old_succs) |
6372 goto rescan; | 6374 { |
6373 } | 6375 if (sched_verbose >= 6) |
6374 | 6376 sel_print ("Rescan: CFG was simplified below insn %d, block %d\n", |
6375 #ifdef ENABLE_CHECKING | 6377 INSN_UID (insn), BLOCK_FOR_INSN (insn)->index); |
6378 insn = sel_bb_end (BLOCK_FOR_INSN (insn)); | |
6379 goto rescan; | |
6380 } | |
6381 } | |
6382 | |
6376 /* Here, RES==1 if original expr was found at least for one of the | 6383 /* Here, RES==1 if original expr was found at least for one of the |
6377 successors. After the loop, RES may happen to have zero value | 6384 successors. After the loop, RES may happen to have zero value |
6378 only if at some point the expr searched is present in av_set, but is | 6385 only if at some point the expr searched is present in av_set, but is |
6379 not found below. In most cases, this situation is an error. | 6386 not found below. In most cases, this situation is an error. |
6380 The exception is when the original operation is blocked by | 6387 The exception is when the original operation is blocked by |
6381 bookkeeping generated for another fence or for another path in current | 6388 bookkeeping generated for another fence or for another path in current |
6382 move_op. */ | 6389 move_op. */ |
6383 gcc_assert (res == 1 | 6390 gcc_checking_assert (res == 1 |
6384 || (res == 0 | 6391 || (res == 0 |
6385 && av_set_could_be_blocked_by_bookkeeping_p (orig_ops, | 6392 && av_set_could_be_blocked_by_bookkeeping_p (orig_ops, static_params)) |
6386 static_params)) | 6393 || res == -1); |
6387 || res == -1); | |
6388 #endif | |
6389 | 6394 |
6390 /* Merge data, clean up, etc. */ | 6395 /* Merge data, clean up, etc. */ |
6391 if (res != -1 && code_motion_path_driver_info->after_merge_succs) | 6396 if (res != -1 && code_motion_path_driver_info->after_merge_succs) |
6392 code_motion_path_driver_info->after_merge_succs (&lparams, static_params); | 6397 code_motion_path_driver_info->after_merge_succs (&lparams, static_params); |
6393 | 6398 |
6459 | 6464 |
6460 if (bitmap_bit_p (code_motion_visited_blocks, bb->index)) | 6465 if (bitmap_bit_p (code_motion_visited_blocks, bb->index)) |
6461 { | 6466 { |
6462 /* We have already found an original operation on this branch, do not | 6467 /* We have already found an original operation on this branch, do not |
6463 go any further and just return TRUE here. If we don't stop here, | 6468 go any further and just return TRUE here. If we don't stop here, |
6464 function can have exponential behaviour even on the small code | 6469 function can have exponential behavior even on the small code |
6465 with many different paths (e.g. with data speculation and | 6470 with many different paths (e.g. with data speculation and |
6466 recovery blocks). */ | 6471 recovery blocks). */ |
6467 if (sched_verbose >= 6) | 6472 if (sched_verbose >= 6) |
6468 sel_print ("Block %d already visited in this traversal\n", bb->index); | 6473 sel_print ("Block %d already visited in this traversal\n", bb->index); |
6469 if (code_motion_path_driver_info->on_enter) | 6474 if (code_motion_path_driver_info->on_enter) |
6479 static_params, false); | 6484 static_params, false); |
6480 orig_ops = av_set_copy (orig_ops); | 6485 orig_ops = av_set_copy (orig_ops); |
6481 | 6486 |
6482 /* Filter the orig_ops set. */ | 6487 /* Filter the orig_ops set. */ |
6483 if (AV_SET_VALID_P (insn)) | 6488 if (AV_SET_VALID_P (insn)) |
6484 av_set_intersect (&orig_ops, AV_SET (insn)); | 6489 av_set_code_motion_filter (&orig_ops, AV_SET (insn)); |
6485 | 6490 |
6486 /* If no more original ops, return immediately. */ | 6491 /* If no more original ops, return immediately. */ |
6487 if (!orig_ops) | 6492 if (!orig_ops) |
6488 { | 6493 { |
6489 if (sched_verbose >= 6) | 6494 if (sched_verbose >= 6) |
6585 /* Here INSN either points to the insn before the original insn (may be | 6590 /* Here INSN either points to the insn before the original insn (may be |
6586 bb_note, if original insn was a bb_head) or to the bb_end. */ | 6591 bb_note, if original insn was a bb_head) or to the bb_end. */ |
6587 if (!expr) | 6592 if (!expr) |
6588 { | 6593 { |
6589 int res; | 6594 int res; |
6595 rtx_insn *last_insn = PREV_INSN (insn); | |
6596 bool added_to_path; | |
6590 | 6597 |
6591 gcc_assert (insn == sel_bb_end (bb)); | 6598 gcc_assert (insn == sel_bb_end (bb)); |
6592 | 6599 |
6593 /* Add bb tail to PATH (but it doesn't make any sense if it's a bb_head - | 6600 /* Add bb tail to PATH (but it doesn't make any sense if it's a bb_head - |
6594 it's already in PATH then). */ | 6601 it's already in PATH then). */ |
6595 if (insn != first_insn) | 6602 if (insn != first_insn) |
6596 ilist_add (&path, insn); | 6603 { |
6604 ilist_add (&path, insn); | |
6605 added_to_path = true; | |
6606 } | |
6607 else | |
6608 added_to_path = false; | |
6597 | 6609 |
6598 /* Process_successors should be able to find at least one | 6610 /* Process_successors should be able to find at least one |
6599 successor for which code_motion_path_driver returns TRUE. */ | 6611 successor for which code_motion_path_driver returns TRUE. */ |
6600 res = code_motion_process_successors (insn, orig_ops, | 6612 res = code_motion_process_successors (insn, orig_ops, |
6601 path, static_params); | 6613 path, static_params); |
6602 | 6614 |
6615 /* Jump in the end of basic block could have been removed or replaced | |
6616 during code_motion_process_successors, so recompute insn as the | |
6617 last insn in bb. */ | |
6618 if (NEXT_INSN (last_insn) != insn) | |
6619 { | |
6620 insn = sel_bb_end (bb); | |
6621 first_insn = sel_bb_head (bb); | |
6622 } | |
6623 | |
6603 /* Remove bb tail from path. */ | 6624 /* Remove bb tail from path. */ |
6604 if (insn != first_insn) | 6625 if (added_to_path) |
6605 ilist_remove (&path); | 6626 ilist_remove (&path); |
6606 | 6627 |
6607 if (res != 1) | 6628 if (res != 1) |
6608 { | 6629 { |
6609 /* This is the case when one of the original expr is no longer available | 6630 /* This is the case when one of the original expr is no longer available |
6639 | 6660 |
6640 /* This should be the very last operation as at bb head we could change | 6661 /* This should be the very last operation as at bb head we could change |
6641 the numbering by creating bookkeeping blocks. */ | 6662 the numbering by creating bookkeeping blocks. */ |
6642 if (removed_last_insn) | 6663 if (removed_last_insn) |
6643 insn = PREV_INSN (insn); | 6664 insn = PREV_INSN (insn); |
6644 bitmap_set_bit (code_motion_visited_blocks, BLOCK_FOR_INSN (insn)->index); | 6665 |
6666 /* If we have simplified the control flow and removed the first jump insn, | |
6667 there's no point in marking this block in the visited blocks bitmap. */ | |
6668 if (BLOCK_FOR_INSN (insn)) | |
6669 bitmap_set_bit (code_motion_visited_blocks, BLOCK_FOR_INSN (insn)->index); | |
6645 return true; | 6670 return true; |
6646 } | 6671 } |
6647 | 6672 |
6648 /* Move up the operations from ORIG_OPS set traversing the dag starting | 6673 /* Move up the operations from ORIG_OPS set traversing the dag starting |
6649 from INSN. PATH represents the edges traversed so far. | 6674 from INSN. PATH represents the edges traversed so far. |
6659 move_op (insn_t insn, av_set_t orig_ops, expr_t expr_vliw, | 6684 move_op (insn_t insn, av_set_t orig_ops, expr_t expr_vliw, |
6660 rtx dest, expr_t c_expr, bool *should_move) | 6685 rtx dest, expr_t c_expr, bool *should_move) |
6661 { | 6686 { |
6662 struct moveop_static_params sparams; | 6687 struct moveop_static_params sparams; |
6663 struct cmpd_local_params lparams; | 6688 struct cmpd_local_params lparams; |
6664 bool res; | 6689 int res; |
6665 | 6690 |
6666 /* Init params for code_motion_path_driver. */ | 6691 /* Init params for code_motion_path_driver. */ |
6667 sparams.dest = dest; | 6692 sparams.dest = dest; |
6668 sparams.c_expr = c_expr; | 6693 sparams.c_expr = c_expr; |
6669 sparams.uid = INSN_UID (EXPR_INSN_RTX (expr_vliw)); | 6694 sparams.uid = INSN_UID (EXPR_INSN_RTX (expr_vliw)); |
6670 #ifdef ENABLE_CHECKING | |
6671 sparams.failed_insn = NULL; | 6695 sparams.failed_insn = NULL; |
6672 #endif | |
6673 sparams.was_renamed = false; | 6696 sparams.was_renamed = false; |
6674 lparams.e1 = NULL; | 6697 lparams.e1 = NULL; |
6675 | 6698 |
6676 /* We haven't visited any blocks yet. */ | 6699 /* We haven't visited any blocks yet. */ |
6677 bitmap_clear (code_motion_visited_blocks); | 6700 bitmap_clear (code_motion_visited_blocks); |
6678 | 6701 |
6679 /* Set appropriate hooks and data. */ | 6702 /* Set appropriate hooks and data. */ |
6680 code_motion_path_driver_info = &move_op_hooks; | 6703 code_motion_path_driver_info = &move_op_hooks; |
6681 res = code_motion_path_driver (insn, orig_ops, NULL, &lparams, &sparams); | 6704 res = code_motion_path_driver (insn, orig_ops, NULL, &lparams, &sparams); |
6705 | |
6706 gcc_assert (res != -1); | |
6682 | 6707 |
6683 if (sparams.was_renamed) | 6708 if (sparams.was_renamed) |
6684 EXPR_WAS_RENAMED (expr_vliw) = true; | 6709 EXPR_WAS_RENAMED (expr_vliw) = true; |
6685 | 6710 |
6686 *should_move = (sparams.uid == -1); | 6711 *should_move = (sparams.uid == -1); |
6699 Clear visited blocks from BLOCKS_TO_RESCHEDULE. */ | 6724 Clear visited blocks from BLOCKS_TO_RESCHEDULE. */ |
6700 static void | 6725 static void |
6701 init_seqno_1 (basic_block bb, sbitmap visited_bbs, bitmap blocks_to_reschedule) | 6726 init_seqno_1 (basic_block bb, sbitmap visited_bbs, bitmap blocks_to_reschedule) |
6702 { | 6727 { |
6703 int bbi = BLOCK_TO_BB (bb->index); | 6728 int bbi = BLOCK_TO_BB (bb->index); |
6704 insn_t insn, note = bb_note (bb); | 6729 insn_t insn; |
6705 insn_t succ_insn; | 6730 insn_t succ_insn; |
6706 succ_iterator si; | 6731 succ_iterator si; |
6707 | 6732 |
6708 SET_BIT (visited_bbs, bbi); | 6733 rtx_note *note = bb_note (bb); |
6734 bitmap_set_bit (visited_bbs, bbi); | |
6709 if (blocks_to_reschedule) | 6735 if (blocks_to_reschedule) |
6710 bitmap_clear_bit (blocks_to_reschedule, bb->index); | 6736 bitmap_clear_bit (blocks_to_reschedule, bb->index); |
6711 | 6737 |
6712 FOR_EACH_SUCC_1 (succ_insn, si, BB_END (bb), | 6738 FOR_EACH_SUCC_1 (succ_insn, si, BB_END (bb), |
6713 SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS) | 6739 SUCCS_NORMAL | SUCCS_SKIP_TO_LOOP_EXITS) |
6715 basic_block succ = BLOCK_FOR_INSN (succ_insn); | 6741 basic_block succ = BLOCK_FOR_INSN (succ_insn); |
6716 int succ_bbi = BLOCK_TO_BB (succ->index); | 6742 int succ_bbi = BLOCK_TO_BB (succ->index); |
6717 | 6743 |
6718 gcc_assert (in_current_region_p (succ)); | 6744 gcc_assert (in_current_region_p (succ)); |
6719 | 6745 |
6720 if (!TEST_BIT (visited_bbs, succ_bbi)) | 6746 if (!bitmap_bit_p (visited_bbs, succ_bbi)) |
6721 { | 6747 { |
6722 gcc_assert (succ_bbi > bbi); | 6748 gcc_assert (succ_bbi > bbi); |
6723 | 6749 |
6724 init_seqno_1 (succ, visited_bbs, blocks_to_reschedule); | 6750 init_seqno_1 (succ, visited_bbs, blocks_to_reschedule); |
6725 } | 6751 } |
6729 | 6755 |
6730 for (insn = BB_END (bb); insn != note; insn = PREV_INSN (insn)) | 6756 for (insn = BB_END (bb); insn != note; insn = PREV_INSN (insn)) |
6731 INSN_SEQNO (insn) = cur_seqno--; | 6757 INSN_SEQNO (insn) = cur_seqno--; |
6732 } | 6758 } |
6733 | 6759 |
6734 /* Initialize seqnos for the current region. NUMBER_OF_INSNS is the number | 6760 /* Initialize seqnos for the current region. BLOCKS_TO_RESCHEDULE contains |
6735 of instructions in the region, BLOCKS_TO_RESCHEDULE contains blocks on | 6761 blocks on which we're rescheduling when pipelining, FROM is the block where |
6736 which we're rescheduling when pipelining, FROM is the block where | |
6737 traversing region begins (it may not be the head of the region when | 6762 traversing region begins (it may not be the head of the region when |
6738 pipelining, but the head of the loop instead). | 6763 pipelining, but the head of the loop instead). |
6739 | 6764 |
6740 Returns the maximal seqno found. */ | 6765 Returns the maximal seqno found. */ |
6741 static int | 6766 static int |
6742 init_seqno (int number_of_insns, bitmap blocks_to_reschedule, basic_block from) | 6767 init_seqno (bitmap blocks_to_reschedule, basic_block from) |
6743 { | 6768 { |
6744 sbitmap visited_bbs; | |
6745 bitmap_iterator bi; | 6769 bitmap_iterator bi; |
6746 unsigned bbi; | 6770 unsigned bbi; |
6747 | 6771 |
6748 visited_bbs = sbitmap_alloc (current_nr_blocks); | 6772 auto_sbitmap visited_bbs (current_nr_blocks); |
6749 | 6773 |
6750 if (blocks_to_reschedule) | 6774 if (blocks_to_reschedule) |
6751 { | 6775 { |
6752 sbitmap_ones (visited_bbs); | 6776 bitmap_ones (visited_bbs); |
6753 EXECUTE_IF_SET_IN_BITMAP (blocks_to_reschedule, 0, bbi, bi) | 6777 EXECUTE_IF_SET_IN_BITMAP (blocks_to_reschedule, 0, bbi, bi) |
6754 { | 6778 { |
6755 gcc_assert (BLOCK_TO_BB (bbi) < current_nr_blocks); | 6779 gcc_assert (BLOCK_TO_BB (bbi) < current_nr_blocks); |
6756 RESET_BIT (visited_bbs, BLOCK_TO_BB (bbi)); | 6780 bitmap_clear_bit (visited_bbs, BLOCK_TO_BB (bbi)); |
6757 } | 6781 } |
6758 } | 6782 } |
6759 else | 6783 else |
6760 { | 6784 { |
6761 sbitmap_zero (visited_bbs); | 6785 bitmap_clear (visited_bbs); |
6762 from = EBB_FIRST_BB (0); | 6786 from = EBB_FIRST_BB (0); |
6763 } | 6787 } |
6764 | 6788 |
6765 cur_seqno = number_of_insns > 0 ? number_of_insns : sched_max_luid - 1; | 6789 cur_seqno = sched_max_luid - 1; |
6766 init_seqno_1 (from, visited_bbs, blocks_to_reschedule); | 6790 init_seqno_1 (from, visited_bbs, blocks_to_reschedule); |
6767 gcc_assert (cur_seqno == 0 || number_of_insns == 0); | 6791 |
6768 | 6792 /* cur_seqno may be positive if the number of instructions is less than |
6769 sbitmap_free (visited_bbs); | 6793 sched_max_luid - 1 (when rescheduling or if some instructions have been |
6794 removed by the call to purge_empty_blocks in sel_sched_region_1). */ | |
6795 gcc_assert (cur_seqno >= 0); | |
6796 | |
6770 return sched_max_luid - 1; | 6797 return sched_max_luid - 1; |
6771 } | 6798 } |
6772 | 6799 |
6773 /* Initialize scheduling parameters for current region. */ | 6800 /* Initialize scheduling parameters for current region. */ |
6774 static void | 6801 static void |
6776 { | 6803 { |
6777 enable_schedule_as_rhs_p = 1; | 6804 enable_schedule_as_rhs_p = 1; |
6778 bookkeeping_p = 1; | 6805 bookkeeping_p = 1; |
6779 pipelining_p = (bookkeeping_p | 6806 pipelining_p = (bookkeeping_p |
6780 && (flag_sel_sched_pipelining != 0) | 6807 && (flag_sel_sched_pipelining != 0) |
6781 && current_loop_nest != NULL); | 6808 && current_loop_nest != NULL |
6809 && loop_has_exit_edges (current_loop_nest)); | |
6782 max_insns_to_rename = PARAM_VALUE (PARAM_SELSCHED_INSNS_TO_RENAME); | 6810 max_insns_to_rename = PARAM_VALUE (PARAM_SELSCHED_INSNS_TO_RENAME); |
6783 max_ws = MAX_WS; | 6811 max_ws = MAX_WS; |
6784 } | 6812 } |
6785 | 6813 |
6786 /* Return true if all basic blocks of current region are empty. */ | 6814 /* Return true if all basic blocks of current region are empty. */ |
6787 static bool | 6815 static bool |
6788 current_region_empty_p (void) | 6816 current_region_empty_p (void) |
6789 { | 6817 { |
6790 int i; | 6818 int i; |
6791 for (i = 0; i < current_nr_blocks; i++) | 6819 for (i = 0; i < current_nr_blocks; i++) |
6792 if (! sel_bb_empty_p (BASIC_BLOCK (BB_TO_BLOCK (i)))) | 6820 if (! sel_bb_empty_p (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i)))) |
6793 return false; | 6821 return false; |
6794 | 6822 |
6795 return true; | 6823 return true; |
6796 } | 6824 } |
6797 | 6825 |
6798 /* Prepare and verify loop nest for pipelining. */ | 6826 /* Prepare and verify loop nest for pipelining. */ |
6799 static void | 6827 static void |
6800 setup_current_loop_nest (int rgn) | 6828 setup_current_loop_nest (int rgn, bb_vec_t *bbs) |
6801 { | 6829 { |
6802 current_loop_nest = get_loop_nest_for_rgn (rgn); | 6830 current_loop_nest = get_loop_nest_for_rgn (rgn); |
6803 | 6831 |
6804 if (!current_loop_nest) | 6832 if (!current_loop_nest) |
6805 return; | 6833 return; |
6806 | 6834 |
6807 /* If this loop has any saved loop preheaders from nested loops, | 6835 /* If this loop has any saved loop preheaders from nested loops, |
6808 add these basic blocks to the current region. */ | 6836 add these basic blocks to the current region. */ |
6809 sel_add_loop_preheaders (); | 6837 sel_add_loop_preheaders (bbs); |
6810 | 6838 |
6811 /* Check that we're starting with a valid information. */ | 6839 /* Check that we're starting with a valid information. */ |
6812 gcc_assert (loop_latch_edge (current_loop_nest)); | 6840 gcc_assert (loop_latch_edge (current_loop_nest)); |
6813 gcc_assert (LOOP_MARKED_FOR_PIPELINING_P (current_loop_nest)); | 6841 gcc_assert (LOOP_MARKED_FOR_PIPELINING_P (current_loop_nest)); |
6814 } | 6842 } |
6843 do region initialization here so the region can be bundled correctly, | 6871 do region initialization here so the region can be bundled correctly, |
6844 but we'll skip the scheduling in sel_sched_region (). */ | 6872 but we'll skip the scheduling in sel_sched_region (). */ |
6845 if (current_region_empty_p ()) | 6873 if (current_region_empty_p ()) |
6846 return true; | 6874 return true; |
6847 | 6875 |
6876 bbs.create (current_nr_blocks); | |
6877 | |
6878 for (i = 0; i < current_nr_blocks; i++) | |
6879 bbs.quick_push (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i))); | |
6880 | |
6881 sel_init_bbs (bbs); | |
6882 | |
6848 if (flag_sel_sched_pipelining) | 6883 if (flag_sel_sched_pipelining) |
6849 setup_current_loop_nest (rgn); | 6884 setup_current_loop_nest (rgn, &bbs); |
6850 | 6885 |
6851 sel_setup_region_sched_flags (); | 6886 sel_setup_region_sched_flags (); |
6852 | |
6853 bbs = VEC_alloc (basic_block, heap, current_nr_blocks); | |
6854 | |
6855 for (i = 0; i < current_nr_blocks; i++) | |
6856 VEC_quick_push (basic_block, bbs, BASIC_BLOCK (BB_TO_BLOCK (i))); | |
6857 | |
6858 sel_init_bbs (bbs, NULL); | |
6859 | 6887 |
6860 /* Initialize luids and dependence analysis which both sel-sched and haifa | 6888 /* Initialize luids and dependence analysis which both sel-sched and haifa |
6861 need. */ | 6889 need. */ |
6862 sched_init_luids (bbs, NULL, NULL, NULL); | 6890 sched_init_luids (bbs); |
6863 sched_deps_init (false); | 6891 sched_deps_init (false); |
6864 | 6892 |
6865 /* Initialize haifa data. */ | 6893 /* Initialize haifa data. */ |
6866 rgn_setup_sched_infos (); | 6894 rgn_setup_sched_infos (); |
6867 sel_set_sched_flags (); | 6895 sel_set_sched_flags (); |
6868 haifa_init_h_i_d (bbs, NULL, NULL, NULL); | 6896 haifa_init_h_i_d (bbs); |
6869 | 6897 |
6870 sel_compute_priorities (rgn); | 6898 sel_compute_priorities (rgn); |
6871 init_deps_global (); | 6899 init_deps_global (); |
6872 | 6900 |
6873 /* Main initialization. */ | 6901 /* Main initialization. */ |
6874 sel_setup_sched_infos (); | 6902 sel_setup_sched_infos (); |
6875 sel_init_global_and_expr (bbs); | 6903 sel_init_global_and_expr (bbs); |
6876 | 6904 |
6877 VEC_free (basic_block, heap, bbs); | 6905 bbs.release (); |
6878 | 6906 |
6879 blocks_to_reschedule = BITMAP_ALLOC (NULL); | 6907 blocks_to_reschedule = BITMAP_ALLOC (NULL); |
6880 | 6908 |
6881 /* Init correct liveness sets on each instruction of a single-block loop. | 6909 /* Init correct liveness sets on each instruction of a single-block loop. |
6882 This is the only situation when we can't update liveness when calling | 6910 This is the only situation when we can't update liveness when calling |
6883 compute_live for the first insn of the loop. */ | 6911 compute_live for the first insn of the loop. */ |
6884 if (current_loop_nest) | 6912 if (current_loop_nest) |
6885 { | 6913 { |
6886 int header = (sel_is_loop_preheader_p (BASIC_BLOCK (BB_TO_BLOCK (0))) | 6914 int header = |
6887 ? 1 | 6915 (sel_is_loop_preheader_p (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (0))) |
6888 : 0); | 6916 ? 1 |
6917 : 0); | |
6889 | 6918 |
6890 if (current_nr_blocks == header + 1) | 6919 if (current_nr_blocks == header + 1) |
6891 update_liveness_on_insn | 6920 update_liveness_on_insn |
6892 (sel_bb_head (BASIC_BLOCK (BB_TO_BLOCK (header)))); | 6921 (sel_bb_head (BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (header)))); |
6893 } | 6922 } |
6894 | 6923 |
6895 /* Set hooks so that no newly generated insn will go out unnoticed. */ | 6924 /* Set hooks so that no newly generated insn will go out unnoticed. */ |
6896 sel_register_cfg_hooks (); | 6925 sel_register_cfg_hooks (); |
6897 | 6926 |
6925 { | 6954 { |
6926 int i; | 6955 int i; |
6927 | 6956 |
6928 for (i = 0; i < current_nr_blocks; i++) | 6957 for (i = 0; i < current_nr_blocks; i++) |
6929 { | 6958 { |
6930 basic_block bb = BASIC_BLOCK (BB_TO_BLOCK (i)); | 6959 basic_block bb = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (i)); |
6931 rtx insn; | 6960 rtx_insn *insn; |
6932 | 6961 |
6933 FOR_BB_INSNS (bb, insn) | 6962 FOR_BB_INSNS (bb, insn) |
6934 if (INSN_P (insn)) | 6963 if (INSN_P (insn)) |
6935 { | 6964 { |
6936 expr_t expr = INSN_EXPR (insn); | 6965 expr_t expr = INSN_EXPR (insn); |
6945 this EBB in SCHEDULED_BLOCKS and appropriately filling in HEAD, TAIL, | 6974 this EBB in SCHEDULED_BLOCKS and appropriately filling in HEAD, TAIL, |
6946 PREV_HEAD, and NEXT_TAIL fields of CURRENT_SCHED_INFO structure. */ | 6975 PREV_HEAD, and NEXT_TAIL fields of CURRENT_SCHED_INFO structure. */ |
6947 static void | 6976 static void |
6948 find_ebb_boundaries (basic_block bb, bitmap scheduled_blocks) | 6977 find_ebb_boundaries (basic_block bb, bitmap scheduled_blocks) |
6949 { | 6978 { |
6950 insn_t head, tail; | 6979 rtx_insn *head, *tail; |
6951 basic_block bb1 = bb; | 6980 basic_block bb1 = bb; |
6952 if (sched_verbose >= 2) | 6981 if (sched_verbose >= 2) |
6953 sel_print ("Finishing schedule in bbs: "); | 6982 sel_print ("Finishing schedule in bbs: "); |
6954 | 6983 |
6955 do | 6984 do |
7100 } | 7129 } |
7101 } | 7130 } |
7102 | 7131 |
7103 if (real_insn) | 7132 if (real_insn) |
7104 { | 7133 { |
7134 static state_t temp = NULL; | |
7135 | |
7136 if (!temp) | |
7137 temp = xmalloc (dfa_state_size); | |
7138 memcpy (temp, curr_state, dfa_state_size); | |
7139 | |
7105 cost = state_transition (curr_state, insn); | 7140 cost = state_transition (curr_state, insn); |
7106 issued_insns++; | 7141 if (memcmp (temp, curr_state, dfa_state_size)) |
7142 issued_insns++; | |
7107 | 7143 |
7108 if (sched_verbose >= 2) | 7144 if (sched_verbose >= 2) |
7109 { | 7145 { |
7110 sel_print ("scheduled insn %d, clock %d\n", INSN_UID (insn), | 7146 sel_print ("scheduled insn %d, clock %d\n", INSN_UID (insn), |
7111 haifa_clock + 1); | 7147 haifa_clock + 1); |
7195 { | 7231 { |
7196 targetm.sched.finish (sched_dump, sched_verbose); | 7232 targetm.sched.finish (sched_dump, sched_verbose); |
7197 | 7233 |
7198 /* Extend luids so that insns generated by the target will | 7234 /* Extend luids so that insns generated by the target will |
7199 get zero luid. */ | 7235 get zero luid. */ |
7200 sched_init_luids (NULL, NULL, NULL, NULL); | 7236 sched_extend_luids (); |
7201 } | 7237 } |
7202 } | 7238 } |
7203 | 7239 |
7204 BITMAP_FREE (scheduled_blocks); | 7240 BITMAP_FREE (scheduled_blocks); |
7205 } | 7241 } |
7213 simplify_changed_insns (); | 7249 simplify_changed_insns (); |
7214 sched_finish_ready_list (); | 7250 sched_finish_ready_list (); |
7215 free_nop_pool (); | 7251 free_nop_pool (); |
7216 | 7252 |
7217 /* Free the vectors. */ | 7253 /* Free the vectors. */ |
7218 if (vec_av_set) | 7254 vec_av_set.release (); |
7219 VEC_free (expr_t, heap, vec_av_set); | |
7220 BITMAP_FREE (current_copies); | 7255 BITMAP_FREE (current_copies); |
7221 BITMAP_FREE (current_originators); | 7256 BITMAP_FREE (current_originators); |
7222 BITMAP_FREE (code_motion_visited_blocks); | 7257 BITMAP_FREE (code_motion_visited_blocks); |
7223 vinsn_vec_free (&vec_bookkeeping_blocked_vinsns); | 7258 vinsn_vec_free (vec_bookkeeping_blocked_vinsns); |
7224 vinsn_vec_free (&vec_target_unavailable_vinsns); | 7259 vinsn_vec_free (vec_target_unavailable_vinsns); |
7225 | 7260 |
7226 /* If LV_SET of the region head should be updated, do it now because | 7261 /* If LV_SET of the region head should be updated, do it now because |
7227 there will be no other chance. */ | 7262 there will be no other chance. */ |
7228 { | 7263 { |
7229 succ_iterator si; | 7264 succ_iterator si; |
7249 | 7284 |
7250 free_nop_vinsn (); | 7285 free_nop_vinsn (); |
7251 | 7286 |
7252 finish_deps_global (); | 7287 finish_deps_global (); |
7253 sched_finish_luids (); | 7288 sched_finish_luids (); |
7289 h_d_i_d.release (); | |
7254 | 7290 |
7255 sel_finish_bbs (); | 7291 sel_finish_bbs (); |
7256 BITMAP_FREE (blocks_to_reschedule); | 7292 BITMAP_FREE (blocks_to_reschedule); |
7257 | 7293 |
7258 sel_unregister_cfg_hooks (); | 7294 sel_unregister_cfg_hooks (); |
7344 else if (*max_seqno < seqno) | 7380 else if (*max_seqno < seqno) |
7345 *max_seqno = seqno; | 7381 *max_seqno = seqno; |
7346 } | 7382 } |
7347 } | 7383 } |
7348 | 7384 |
7349 /* Calculate new fences from FENCES. */ | 7385 /* Calculate new fences from FENCES. Write the current time to PTIME. */ |
7350 static flist_t | 7386 static flist_t |
7351 calculate_new_fences (flist_t fences, int orig_max_seqno) | 7387 calculate_new_fences (flist_t fences, int orig_max_seqno, int *ptime) |
7352 { | 7388 { |
7353 flist_t old_fences = fences; | 7389 flist_t old_fences = fences; |
7354 struct flist_tail_def _new_fences, *new_fences = &_new_fences; | 7390 struct flist_tail_def _new_fences, *new_fences = &_new_fences; |
7391 int max_time = 0; | |
7355 | 7392 |
7356 flist_tail_init (new_fences); | 7393 flist_tail_init (new_fences); |
7357 for (; fences; fences = FLIST_NEXT (fences)) | 7394 for (; fences; fences = FLIST_NEXT (fences)) |
7358 { | 7395 { |
7359 fence_t fence = FLIST_FENCE (fences); | 7396 fence_t fence = FLIST_FENCE (fences); |
7378 move_fence_to_fences (fences, new_fences); | 7415 move_fence_to_fences (fences, new_fences); |
7379 } | 7416 } |
7380 } | 7417 } |
7381 else | 7418 else |
7382 extract_new_fences_from (fences, new_fences, orig_max_seqno); | 7419 extract_new_fences_from (fences, new_fences, orig_max_seqno); |
7420 max_time = MAX (max_time, FENCE_CYCLE (fence)); | |
7383 } | 7421 } |
7384 | 7422 |
7385 flist_clear (&old_fences); | 7423 flist_clear (&old_fences); |
7424 *ptime = max_time; | |
7386 return FLIST_TAIL_HEAD (new_fences); | 7425 return FLIST_TAIL_HEAD (new_fences); |
7387 } | 7426 } |
7388 | 7427 |
7389 /* Update seqnos of insns given by PSCHEDULED_INSNS. MIN_SEQNO and MAX_SEQNO | 7428 /* Update seqnos of insns given by PSCHEDULED_INSNS. MIN_SEQNO and MAX_SEQNO |
7390 are the miminum and maximum seqnos of the group, HIGHEST_SEQNO_IN_USE is | 7429 are the miminum and maximum seqnos of the group, HIGHEST_SEQNO_IN_USE is |
7435 of scheduling. */ | 7474 of scheduling. */ |
7436 static void | 7475 static void |
7437 sel_sched_region_2 (int orig_max_seqno) | 7476 sel_sched_region_2 (int orig_max_seqno) |
7438 { | 7477 { |
7439 int highest_seqno_in_use = orig_max_seqno; | 7478 int highest_seqno_in_use = orig_max_seqno; |
7479 int max_time = 0; | |
7440 | 7480 |
7441 stat_bookkeeping_copies = 0; | 7481 stat_bookkeeping_copies = 0; |
7442 stat_insns_needed_bookkeeping = 0; | 7482 stat_insns_needed_bookkeeping = 0; |
7443 stat_renamed_scheduled = 0; | 7483 stat_renamed_scheduled = 0; |
7444 stat_substitutions_total = 0; | 7484 stat_substitutions_total = 0; |
7450 ilist_t scheduled_insns = NULL; | 7490 ilist_t scheduled_insns = NULL; |
7451 ilist_t *scheduled_insns_tailp = &scheduled_insns; | 7491 ilist_t *scheduled_insns_tailp = &scheduled_insns; |
7452 | 7492 |
7453 find_min_max_seqno (fences, &min_seqno, &max_seqno); | 7493 find_min_max_seqno (fences, &min_seqno, &max_seqno); |
7454 schedule_on_fences (fences, max_seqno, &scheduled_insns_tailp); | 7494 schedule_on_fences (fences, max_seqno, &scheduled_insns_tailp); |
7455 fences = calculate_new_fences (fences, orig_max_seqno); | 7495 fences = calculate_new_fences (fences, orig_max_seqno, &max_time); |
7456 highest_seqno_in_use = update_seqnos_and_stage (min_seqno, max_seqno, | 7496 highest_seqno_in_use = update_seqnos_and_stage (min_seqno, max_seqno, |
7457 highest_seqno_in_use, | 7497 highest_seqno_in_use, |
7458 &scheduled_insns); | 7498 &scheduled_insns); |
7459 } | 7499 } |
7460 | 7500 |
7461 if (sched_verbose >= 1) | 7501 if (sched_verbose >= 1) |
7462 sel_print ("Scheduled %d bookkeeping copies, %d insns needed " | 7502 { |
7463 "bookkeeping, %d insns renamed, %d insns substituted\n", | 7503 sel_print ("Total scheduling time: %d cycles\n", max_time); |
7464 stat_bookkeeping_copies, | 7504 sel_print ("Scheduled %d bookkeeping copies, %d insns needed " |
7465 stat_insns_needed_bookkeeping, | 7505 "bookkeeping, %d insns renamed, %d insns substituted\n", |
7466 stat_renamed_scheduled, | 7506 stat_bookkeeping_copies, |
7467 stat_substitutions_total); | 7507 stat_insns_needed_bookkeeping, |
7508 stat_renamed_scheduled, | |
7509 stat_substitutions_total); | |
7510 } | |
7468 } | 7511 } |
7469 | 7512 |
7470 /* Schedule a region. When pipelining, search for possibly never scheduled | 7513 /* Schedule a region. When pipelining, search for possibly never scheduled |
7471 bookkeeping code and schedule it. Reschedule pipelined code without | 7514 bookkeeping code and schedule it. Reschedule pipelined code without |
7472 pipelining after. */ | 7515 pipelining after. */ |
7473 static void | 7516 static void |
7474 sel_sched_region_1 (void) | 7517 sel_sched_region_1 (void) |
7475 { | 7518 { |
7476 int number_of_insns; | |
7477 int orig_max_seqno; | 7519 int orig_max_seqno; |
7478 | 7520 |
7479 /* Remove empty blocks that might be in the region from the beginning. | 7521 /* Remove empty blocks that might be in the region from the beginning. */ |
7480 We need to do save sched_max_luid before that, as it actually shows | |
7481 the number of insns in the region, and purge_empty_blocks can | |
7482 alter it. */ | |
7483 number_of_insns = sched_max_luid - 1; | |
7484 purge_empty_blocks (); | 7522 purge_empty_blocks (); |
7485 | 7523 |
7486 orig_max_seqno = init_seqno (number_of_insns, NULL, NULL); | 7524 orig_max_seqno = init_seqno (NULL, NULL); |
7487 gcc_assert (orig_max_seqno >= 1); | 7525 gcc_assert (orig_max_seqno >= 1); |
7488 | 7526 |
7489 /* When pipelining outer loops, create fences on the loop header, | 7527 /* When pipelining outer loops, create fences on the loop header, |
7490 not preheader. */ | 7528 not preheader. */ |
7491 fences = NULL; | 7529 fences = NULL; |
7558 | 7596 |
7559 if (bitmap_bit_p (blocks_to_reschedule, bb->index)) | 7597 if (bitmap_bit_p (blocks_to_reschedule, bb->index)) |
7560 { | 7598 { |
7561 flist_tail_init (new_fences); | 7599 flist_tail_init (new_fences); |
7562 | 7600 |
7563 orig_max_seqno = init_seqno (0, blocks_to_reschedule, bb); | 7601 orig_max_seqno = init_seqno (blocks_to_reschedule, bb); |
7564 | 7602 |
7565 /* Mark BB as head of the new ebb. */ | 7603 /* Mark BB as head of the new ebb. */ |
7566 bitmap_set_bit (forced_ebb_heads, bb->index); | 7604 bitmap_set_bit (forced_ebb_heads, bb->index); |
7567 | 7605 |
7568 gcc_assert (fences == NULL); | 7606 gcc_assert (fences == NULL); |
7664 void | 7702 void |
7665 run_selective_scheduling (void) | 7703 run_selective_scheduling (void) |
7666 { | 7704 { |
7667 int rgn; | 7705 int rgn; |
7668 | 7706 |
7669 if (n_basic_blocks == NUM_FIXED_BLOCKS) | 7707 if (n_basic_blocks_for_fn (cfun) == NUM_FIXED_BLOCKS) |
7670 return; | 7708 return; |
7671 | 7709 |
7672 sel_global_init (); | 7710 sel_global_init (); |
7673 | 7711 |
7674 for (rgn = 0; rgn < nr_regions; rgn++) | 7712 for (rgn = 0; rgn < nr_regions; rgn++) |