comparison gcc/sel-sched-ir.h @ 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. This file contains definitions used 1 /* Instruction scheduling pass. This file contains definitions used
2 internally in the scheduler. 2 internally in the scheduler.
3 Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. 3 Copyright (C) 2006-2017 Free Software Foundation, Inc.
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify it under 7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free 8 the terms of the GNU General Public License as published by the Free
20 20
21 #ifndef GCC_SEL_SCHED_IR_H 21 #ifndef GCC_SEL_SCHED_IR_H
22 #define GCC_SEL_SCHED_IR_H 22 #define GCC_SEL_SCHED_IR_H
23 23
24 /* For state_t. */ 24 /* For state_t. */
25 #include "insn-attr.h"
26 #include "regset.h"
27 #include "basic-block.h"
28 /* For reg_note. */ 25 /* For reg_note. */
29 #include "rtl.h"
30 #include "ggc.h"
31 #include "bitmap.h"
32 #include "vecprim.h"
33 #include "sched-int.h"
34 #include "cfgloop.h"
35 26
36 /* tc_t is a short for target context. This is a state of the target 27 /* tc_t is a short for target context. This is a state of the target
37 backend. */ 28 backend. */
38 typedef void *tc_t; 29 typedef void *tc_t;
39 30
59 typedef _list_t _xlist_t; 50 typedef _list_t _xlist_t;
60 #define _XLIST_X(L) ((L)->u.x) 51 #define _XLIST_X(L) ((L)->u.x)
61 #define _XLIST_NEXT(L) (_LIST_NEXT (L)) 52 #define _XLIST_NEXT(L) (_LIST_NEXT (L))
62 53
63 /* Instruction. */ 54 /* Instruction. */
64 typedef rtx insn_t; 55 typedef rtx_insn *insn_t;
65 56
66 /* List of insns. */ 57 /* List of insns. */
67 typedef _xlist_t ilist_t; 58 typedef _list_t ilist_t;
68 #define ILIST_INSN(L) (_XLIST_X (L)) 59 #define ILIST_INSN(L) ((L)->u.insn)
69 #define ILIST_NEXT(L) (_XLIST_NEXT (L)) 60 #define ILIST_NEXT(L) (_LIST_NEXT (L))
70 61
71 /* This lists possible transformations that done locally, i.e. in 62 /* This lists possible transformations that done locally, i.e. in
72 moveup_expr. */ 63 moveup_expr. */
73 enum local_trans_type 64 enum local_trans_type
74 { 65 {
96 enum local_trans_type type; 87 enum local_trans_type type;
97 }; 88 };
98 89
99 typedef struct expr_history_def_1 expr_history_def; 90 typedef struct expr_history_def_1 expr_history_def;
100 91
101 DEF_VEC_O (expr_history_def);
102 DEF_VEC_ALLOC_O (expr_history_def, heap);
103 92
104 /* Expression information. */ 93 /* Expression information. */
105 struct _expr 94 struct _expr
106 { 95 {
107 /* Insn description. */ 96 /* Insn description. */
143 /* Cycle on which original insn was scheduled. Zero when it has not yet 132 /* Cycle on which original insn was scheduled. Zero when it has not yet
144 been scheduled or more than one originator. */ 133 been scheduled or more than one originator. */
145 int orig_sched_cycle; 134 int orig_sched_cycle;
146 135
147 /* This vector contains the history of insn's transformations. */ 136 /* This vector contains the history of insn's transformations. */
148 VEC(expr_history_def, heap) *history_of_changes; 137 vec<expr_history_def> history_of_changes;
149 138
150 /* True (1) when original target (register or memory) of this instruction 139 /* True (1) when original target (register or memory) of this instruction
151 is available for scheduling, false otherwise. -1 means we're not sure; 140 is available for scheduling, false otherwise. -1 means we're not sure;
152 please run find_used_regs to clarify. */ 141 please run find_used_regs to clarify. */
153 signed char target_available; 142 signed char target_available;
192 #define EXPR_NEEDS_SPEC_CHECK_P(EXPR) ((EXPR)->needs_spec_check_p) 181 #define EXPR_NEEDS_SPEC_CHECK_P(EXPR) ((EXPR)->needs_spec_check_p)
193 #define EXPR_WAS_SUBSTITUTED(EXPR) ((EXPR)->was_substituted) 182 #define EXPR_WAS_SUBSTITUTED(EXPR) ((EXPR)->was_substituted)
194 #define EXPR_WAS_RENAMED(EXPR) ((EXPR)->was_renamed) 183 #define EXPR_WAS_RENAMED(EXPR) ((EXPR)->was_renamed)
195 #define EXPR_CANT_MOVE(EXPR) ((EXPR)->cant_move) 184 #define EXPR_CANT_MOVE(EXPR) ((EXPR)->cant_move)
196 185
197 #define EXPR_WAS_CHANGED(EXPR) (VEC_length (expr_history_def, \
198 EXPR_HISTORY_OF_CHANGES (EXPR)) > 0)
199
200 /* Insn definition for list of original insns in find_used_regs. */ 186 /* Insn definition for list of original insns in find_used_regs. */
201 struct _def 187 struct _def
202 { 188 {
203 insn_t orig_insn; 189 insn_t orig_insn;
204 190
282 /* Target context at this fence. Used to save and load any local target 268 /* Target context at this fence. Used to save and load any local target
283 scheduling information when changing fences. */ 269 scheduling information when changing fences. */
284 tc_t tc; 270 tc_t tc;
285 271
286 /* A vector of insns that are scheduled but not yet completed. */ 272 /* A vector of insns that are scheduled but not yet completed. */
287 VEC (rtx,gc) *executing_insns; 273 vec<rtx_insn *, va_gc> *executing_insns;
288 274
289 /* A vector indexed by UIDs that caches the earliest cycle on which 275 /* A vector indexed by UIDs that caches the earliest cycle on which
290 an insn can be scheduled on this fence. */ 276 an insn can be scheduled on this fence. */
291 int *ready_ticks; 277 int *ready_ticks;
292 278
293 /* Its size. */ 279 /* Its size. */
294 int ready_ticks_size; 280 int ready_ticks_size;
295 281
296 /* Insn, which has been scheduled last on this fence. */ 282 /* Insn, which has been scheduled last on this fence. */
297 rtx last_scheduled_insn; 283 rtx_insn *last_scheduled_insn;
298 284
299 /* The last value of can_issue_more variable on this fence. */ 285 /* The last value of can_issue_more variable on this fence. */
300 int issue_more; 286 int issue_more;
301 287
302 /* If non-NULL force the next scheduled insn to be SCHED_NEXT. */ 288 /* If non-NULL force the next scheduled insn to be SCHED_NEXT. */
303 rtx sched_next; 289 rtx_insn *sched_next;
304 290
305 /* True if fill_insns processed this fence. */ 291 /* True if fill_insns processed this fence. */
306 BOOL_BITFIELD processed_p : 1; 292 BOOL_BITFIELD processed_p : 1;
307 293
308 /* True if fill_insns actually scheduled something on this fence. */ 294 /* True if fill_insns actually scheduled something on this fence. */
356 _list_t next; 342 _list_t next;
357 343
358 union 344 union
359 { 345 {
360 rtx x; 346 rtx x;
347 insn_t insn;
361 struct _bnd bnd; 348 struct _bnd bnd;
362 expr_def expr; 349 expr_def expr;
363 struct _fence fence; 350 struct _fence fence;
364 struct _def def; 351 struct _def def;
365 void *data; 352 void *data;
368 355
369 356
370 /* _list_t functions. 357 /* _list_t functions.
371 All of _*list_* functions are used through accessor macros, thus 358 All of _*list_* functions are used through accessor macros, thus
372 we can't move them in sel-sched-ir.c. */ 359 we can't move them in sel-sched-ir.c. */
373 extern alloc_pool sched_lists_pool; 360 extern object_allocator<_list_node> sched_lists_pool;
374 361
375 static inline _list_t 362 static inline _list_t
376 _list_alloc (void) 363 _list_alloc (void)
377 { 364 {
378 return (_list_t) pool_alloc (sched_lists_pool); 365 return sched_lists_pool.allocate ();
379 } 366 }
380 367
381 static inline void 368 static inline void
382 _list_add (_list_t *lp) 369 _list_add (_list_t *lp)
383 { 370 {
399 _list_remove (_list_t *lp) 386 _list_remove (_list_t *lp)
400 { 387 {
401 _list_t n = *lp; 388 _list_t n = *lp;
402 389
403 *lp = _LIST_NEXT (n); 390 *lp = _LIST_NEXT (n);
404 pool_free (sched_lists_pool, n); 391 sched_lists_pool.remove (n);
405 } 392 }
406 393
407 static inline void 394 static inline void
408 _list_clear (_list_t *l) 395 _list_clear (_list_t *l)
409 { 396 {
411 _list_remove (l); 398 _list_remove (l);
412 } 399 }
413 400
414 401
415 /* List iterator backend. */ 402 /* List iterator backend. */
416 typedef struct 403 struct _list_iterator
417 { 404 {
418 /* The list we're iterating. */ 405 /* The list we're iterating. */
419 _list_t *lp; 406 _list_t *lp;
420 407
421 /* True when this iterator supprts removing. */ 408 /* True when this iterator supprts removing. */
422 bool can_remove_p; 409 bool can_remove_p;
423 410
424 /* True when we've actually removed something. */ 411 /* True when we've actually removed something. */
425 bool removed_p; 412 bool removed_p;
426 } _list_iterator; 413 };
427 414
428 static inline void 415 static inline void
429 _list_iter_start (_list_iterator *ip, _list_t *lp, bool can_remove_p) 416 _list_iter_start (_list_iterator *ip, _list_t *lp, bool can_remove_p)
430 { 417 {
431 ip->lp = lp; 418 ip->lp = lp;
514 typedef _list_iterator _xlist_iterator; 501 typedef _list_iterator _xlist_iterator;
515 #define _FOR_EACH_X(X, I, L) _FOR_EACH (x, (X), (I), (L)) 502 #define _FOR_EACH_X(X, I, L) _FOR_EACH (x, (X), (I), (L))
516 #define _FOR_EACH_X_1(X, I, LP) _FOR_EACH_1 (x, (X), (I), (LP)) 503 #define _FOR_EACH_X_1(X, I, LP) _FOR_EACH_1 (x, (X), (I), (LP))
517 504
518 505
519 /* ilist_t functions. Instruction lists are simply RTX lists. */ 506 /* ilist_t functions. */
520 507
521 #define ilist_add(LP, INSN) (_xlist_add ((LP), (INSN))) 508 static inline void
522 #define ilist_remove(LP) (_xlist_remove (LP)) 509 ilist_add (ilist_t *lp, insn_t insn)
523 #define ilist_clear(LP) (_xlist_clear (LP)) 510 {
524 #define ilist_is_in_p(L, INSN) (_xlist_is_in_p ((L), (INSN))) 511 _list_add (lp);
525 #define ilist_iter_remove(IP) (_xlist_iter_remove (IP)) 512 ILIST_INSN (*lp) = insn;
526 513 }
527 typedef _xlist_iterator ilist_iterator; 514 #define ilist_remove(LP) (_list_remove (LP))
528 #define FOR_EACH_INSN(INSN, I, L) _FOR_EACH_X (INSN, I, L) 515 #define ilist_clear(LP) (_list_clear (LP))
529 #define FOR_EACH_INSN_1(INSN, I, LP) _FOR_EACH_X_1 (INSN, I, LP) 516
517 static inline bool
518 ilist_is_in_p (ilist_t l, insn_t insn)
519 {
520 while (l)
521 {
522 if (ILIST_INSN (l) == insn)
523 return true;
524 l = ILIST_NEXT (l);
525 }
526
527 return false;
528 }
529
530 /* Used through _FOR_EACH. */
531 static inline bool
532 _list_iter_cond_insn (ilist_t l, insn_t *ip)
533 {
534 if (l)
535 {
536 *ip = ILIST_INSN (l);
537 return true;
538 }
539
540 return false;
541 }
542
543 #define ilist_iter_remove(IP) (_list_iter_remove (IP))
544
545 typedef _list_iterator ilist_iterator;
546 #define FOR_EACH_INSN(INSN, I, L) _FOR_EACH (insn, (INSN), (I), (L))
547 #define FOR_EACH_INSN_1(INSN, I, LP) _FOR_EACH_1 (insn, (INSN), (I), (LP))
530 548
531 549
532 /* Av set iterators. */ 550 /* Av set iterators. */
533 typedef _list_iterator av_set_iterator; 551 typedef _list_iterator av_set_iterator;
534 #define FOR_EACH_EXPR(EXPR, I, AV) _FOR_EACH (expr, (EXPR), (I), (AV)) 552 #define FOR_EACH_EXPR(EXPR, I, AV) _FOR_EACH (expr, (EXPR), (I), (AV))
535 #define FOR_EACH_EXPR_1(EXPR, I, AV) _FOR_EACH_1 (expr, (EXPR), (I), (AV)) 553 #define FOR_EACH_EXPR_1(EXPR, I, AV) _FOR_EACH_1 (expr, (EXPR), (I), (AV))
536 554
537 static bool 555 inline bool
538 _list_iter_cond_expr (av_set_t av, expr_t *exprp) 556 _list_iter_cond_expr (av_set_t av, expr_t *exprp)
539 { 557 {
540 if (av) 558 if (av)
541 { 559 {
542 *exprp = _AV_SET_EXPR (av); 560 *exprp = _AV_SET_EXPR (av);
627 unusual stuff. Such a vinsn is described by its INSN field, which is a 645 unusual stuff. Such a vinsn is described by its INSN field, which is a
628 reference to the original instruction. */ 646 reference to the original instruction. */
629 struct vinsn_def 647 struct vinsn_def
630 { 648 {
631 /* Associated insn. */ 649 /* Associated insn. */
632 rtx insn_rtx; 650 rtx_insn *insn_rtx;
633 651
634 /* Its description. */ 652 /* Its description. */
635 struct idata_def id; 653 struct idata_def id;
636 654
637 /* Hash of vinsn. It is computed either from pattern or from rhs using 655 /* Hash of vinsn. It is computed either from pattern or from rhs using
757 }; 775 };
758 776
759 typedef struct _sel_insn_data sel_insn_data_def; 777 typedef struct _sel_insn_data sel_insn_data_def;
760 typedef sel_insn_data_def *sel_insn_data_t; 778 typedef sel_insn_data_def *sel_insn_data_t;
761 779
762 DEF_VEC_O (sel_insn_data_def); 780 extern vec<sel_insn_data_def> s_i_d;
763 DEF_VEC_ALLOC_O (sel_insn_data_def, heap);
764 extern VEC (sel_insn_data_def, heap) *s_i_d;
765 781
766 /* Accessor macros for s_i_d. */ 782 /* Accessor macros for s_i_d. */
767 #define SID(INSN) (VEC_index (sel_insn_data_def, s_i_d, INSN_LUID (INSN))) 783 #define SID(INSN) (&s_i_d[INSN_LUID (INSN)])
768 #define SID_BY_UID(UID) (VEC_index (sel_insn_data_def, s_i_d, LUID_BY_UID (UID))) 784 #define SID_BY_UID(UID) (&s_i_d[LUID_BY_UID (UID)])
769 785
770 extern sel_insn_data_def insn_sid (insn_t); 786 extern sel_insn_data_def insn_sid (insn_t);
771 787
772 #define INSN_ASM_P(INSN) (SID (INSN)->asm_p) 788 #define INSN_ASM_P(INSN) (SID (INSN)->asm_p)
773 #define INSN_SCHED_NEXT(INSN) (SID (INSN)->sched_next) 789 #define INSN_SCHED_NEXT(INSN) (SID (INSN)->sched_next)
813 829
814 /* A NOP pattern used as a placeholder for real insns. */ 830 /* A NOP pattern used as a placeholder for real insns. */
815 extern rtx nop_pattern; 831 extern rtx nop_pattern;
816 832
817 /* An insn that 'contained' in EXIT block. */ 833 /* An insn that 'contained' in EXIT block. */
818 extern rtx exit_insn; 834 extern rtx_insn *exit_insn;
819 835
820 /* Provide a separate luid for the insn. */ 836 /* Provide a separate luid for the insn. */
821 #define INSN_INIT_TODO_LUID (1) 837 #define INSN_INIT_TODO_LUID (1)
822 838
823 /* Initialize s_s_i_d. */ 839 /* Initialize s_s_i_d. */
845 #define LOOP_MARKED_FOR_PIPELINING_P(LOOP) ((size_t)((LOOP)->aux)) 861 #define LOOP_MARKED_FOR_PIPELINING_P(LOOP) ((size_t)((LOOP)->aux))
846 862
847 /* Saved loop preheader to transfer when scheduling the loop. */ 863 /* Saved loop preheader to transfer when scheduling the loop. */
848 #define LOOP_PREHEADER_BLOCKS(LOOP) ((size_t)((LOOP)->aux) == 1 \ 864 #define LOOP_PREHEADER_BLOCKS(LOOP) ((size_t)((LOOP)->aux) == 1 \
849 ? NULL \ 865 ? NULL \
850 : ((VEC(basic_block, heap) *) (LOOP)->aux)) 866 : ((vec<basic_block> *) (LOOP)->aux))
851 #define SET_LOOP_PREHEADER_BLOCKS(LOOP,BLOCKS) ((LOOP)->aux \ 867 #define SET_LOOP_PREHEADER_BLOCKS(LOOP,BLOCKS) ((LOOP)->aux \
852 = (BLOCKS != NULL \ 868 = (BLOCKS != NULL \
853 ? BLOCKS \ 869 ? BLOCKS \
854 : (LOOP)->aux)) 870 : (LOOP)->aux))
855 871
856 extern bitmap blocks_to_reschedule; 872 extern bitmap blocks_to_reschedule;
857 873
858 874
859 /* A variable to track which part of rtx we are scanning in 875 /* A variable to track which part of rtx we are scanning in
860 sched-deps.c: sched_analyze_insn (). */ 876 sched-deps.c: sched_analyze_insn (). */
861 enum deps_where_def 877 enum deps_where_t
862 { 878 {
863 DEPS_IN_INSN, 879 DEPS_IN_INSN,
864 DEPS_IN_LHS, 880 DEPS_IN_LHS,
865 DEPS_IN_RHS, 881 DEPS_IN_RHS,
866 DEPS_IN_NOWHERE 882 DEPS_IN_NOWHERE
867 }; 883 };
868 typedef enum deps_where_def deps_where_t;
869 884
870 885
871 /* Per basic block data for the whole CFG. */ 886 /* Per basic block data for the whole CFG. */
872 typedef struct 887 struct sel_global_bb_info_def
873 { 888 {
874 /* For each bb header this field contains a set of live registers. 889 /* For each bb header this field contains a set of live registers.
875 For all other insns this field has a NULL. 890 For all other insns this field has a NULL.
876 We also need to know LV sets for the instructions, that are immediatly 891 We also need to know LV sets for the instructions, that are immediately
877 after the border of the region. */ 892 after the border of the region. */
878 regset lv_set; 893 regset lv_set;
879 894
880 /* Status of LV_SET. 895 /* Status of LV_SET.
881 true - block has usable LV_SET. 896 true - block has usable LV_SET.
882 false - block's LV_SET should be recomputed. */ 897 false - block's LV_SET should be recomputed. */
883 bool lv_set_valid_p; 898 bool lv_set_valid_p;
884 } sel_global_bb_info_def; 899 };
885 900
886 typedef sel_global_bb_info_def *sel_global_bb_info_t; 901 typedef sel_global_bb_info_def *sel_global_bb_info_t;
887 902
888 DEF_VEC_O (sel_global_bb_info_def);
889 DEF_VEC_ALLOC_O (sel_global_bb_info_def, heap);
890 903
891 /* Per basic block data. This array is indexed by basic block index. */ 904 /* Per basic block data. This array is indexed by basic block index. */
892 extern VEC (sel_global_bb_info_def, heap) *sel_global_bb_info; 905 extern vec<sel_global_bb_info_def> sel_global_bb_info;
893 906
894 extern void sel_extend_global_bb_info (void); 907 extern void sel_extend_global_bb_info (void);
895 extern void sel_finish_global_bb_info (void); 908 extern void sel_finish_global_bb_info (void);
896 909
897 /* Get data for BB. */ 910 /* Get data for BB. */
898 #define SEL_GLOBAL_BB_INFO(BB) \ 911 #define SEL_GLOBAL_BB_INFO(BB) \
899 (VEC_index (sel_global_bb_info_def, sel_global_bb_info, (BB)->index)) 912 (&sel_global_bb_info[(BB)->index])
900 913
901 /* Access macros. */ 914 /* Access macros. */
902 #define BB_LV_SET(BB) (SEL_GLOBAL_BB_INFO (BB)->lv_set) 915 #define BB_LV_SET(BB) (SEL_GLOBAL_BB_INFO (BB)->lv_set)
903 #define BB_LV_SET_VALID_P(BB) (SEL_GLOBAL_BB_INFO (BB)->lv_set_valid_p) 916 #define BB_LV_SET_VALID_P(BB) (SEL_GLOBAL_BB_INFO (BB)->lv_set_valid_p)
904 917
905 /* Per basic block data for the region. */ 918 /* Per basic block data for the region. */
906 typedef struct 919 struct sel_region_bb_info_def
907 { 920 {
908 /* This insn stream is constructed in such a way that it should be 921 /* This insn stream is constructed in such a way that it should be
909 traversed by PREV_INSN field - (*not* NEXT_INSN). */ 922 traversed by PREV_INSN field - (*not* NEXT_INSN). */
910 rtx note_list; 923 rtx_insn *note_list;
911 924
912 /* Cached availability set at the beginning of a block. 925 /* Cached availability set at the beginning of a block.
913 See also AV_LEVEL () for conditions when this av_set can be used. */ 926 See also AV_LEVEL () for conditions when this av_set can be used. */
914 av_set_t av_set; 927 av_set_t av_set;
915 928
916 /* If (AV_LEVEL == GLOBAL_LEVEL) then AV is valid. */ 929 /* If (AV_LEVEL == GLOBAL_LEVEL) then AV is valid. */
917 int av_level; 930 int av_level;
918 } sel_region_bb_info_def; 931 };
919 932
920 typedef sel_region_bb_info_def *sel_region_bb_info_t; 933 typedef sel_region_bb_info_def *sel_region_bb_info_t;
921 934
922 DEF_VEC_O (sel_region_bb_info_def);
923 DEF_VEC_ALLOC_O (sel_region_bb_info_def, heap);
924 935
925 /* Per basic block data. This array is indexed by basic block index. */ 936 /* Per basic block data. This array is indexed by basic block index. */
926 extern VEC (sel_region_bb_info_def, heap) *sel_region_bb_info; 937 extern vec<sel_region_bb_info_def> sel_region_bb_info;
927 938
928 /* Get data for BB. */ 939 /* Get data for BB. */
929 #define SEL_REGION_BB_INFO(BB) (VEC_index (sel_region_bb_info_def, \ 940 #define SEL_REGION_BB_INFO(BB) (&sel_region_bb_info[(BB)->index])
930 sel_region_bb_info, (BB)->index))
931 941
932 /* Get BB's note_list. 942 /* Get BB's note_list.
933 A note_list is a list of various notes that was scattered across BB 943 A note_list is a list of various notes that was scattered across BB
934 before scheduling, and will be appended at the beginning of BB after 944 before scheduling, and will be appended at the beginning of BB after
935 scheduling is finished. */ 945 scheduling is finished. */
962 972
963 extern regset sel_all_regs; 973 extern regset sel_all_regs;
964 974
965 975
966 /* Successor iterator backend. */ 976 /* Successor iterator backend. */
967 typedef struct 977 struct succ_iterator
968 { 978 {
969 /* True if we're at BB end. */ 979 /* True if we're at BB end. */
970 bool bb_end; 980 bool bb_end;
971 981
972 /* An edge on which we're iterating. */ 982 /* An edge on which we're iterating. */
984 /* Flags that are passed to the iterator. We return only successors 994 /* Flags that are passed to the iterator. We return only successors
985 that comply to these flags. */ 995 that comply to these flags. */
986 short flags; 996 short flags;
987 997
988 /* When flags include SUCCS_ALL, this will be set to the exact type 998 /* When flags include SUCCS_ALL, this will be set to the exact type
989 of the sucessor we're traversing now. */ 999 of the successor we're traversing now. */
990 short current_flags; 1000 short current_flags;
991 1001
992 /* If skip to loop exits, save here information about loop exits. */ 1002 /* If skip to loop exits, save here information about loop exits. */
993 int current_exit; 1003 int current_exit;
994 VEC (edge, heap) *loop_exits; 1004 vec<edge> loop_exits;
995 } succ_iterator; 1005 };
996 1006
997 /* A structure returning all successor's information. */ 1007 /* A structure returning all successor's information. */
998 struct succs_info 1008 struct succs_info
999 { 1009 {
1000 /* Flags that these succcessors were computed with. */ 1010 /* Flags that these succcessors were computed with. */
1003 /* Successors that correspond to the flags. */ 1013 /* Successors that correspond to the flags. */
1004 insn_vec_t succs_ok; 1014 insn_vec_t succs_ok;
1005 1015
1006 /* Their probabilities. As of now, we don't need this for other 1016 /* Their probabilities. As of now, we don't need this for other
1007 successors. */ 1017 successors. */
1008 VEC(int,heap) *probs_ok; 1018 vec<int> probs_ok;
1009 1019
1010 /* Other successors. */ 1020 /* Other successors. */
1011 insn_vec_t succs_other; 1021 insn_vec_t succs_other;
1012 1022
1013 /* Probability of all successors. */ 1023 /* Probability of all successors. */
1021 }; 1031 };
1022 1032
1023 /* Some needed definitions. */ 1033 /* Some needed definitions. */
1024 extern basic_block after_recovery; 1034 extern basic_block after_recovery;
1025 1035
1026 extern insn_t sel_bb_head (basic_block); 1036 extern rtx_insn *sel_bb_head (basic_block);
1027 extern insn_t sel_bb_end (basic_block); 1037 extern rtx_insn *sel_bb_end (basic_block);
1028 extern bool sel_bb_empty_p (basic_block); 1038 extern bool sel_bb_empty_p (basic_block);
1029 extern bool in_current_region_p (basic_block); 1039 extern bool in_current_region_p (basic_block);
1030 1040
1031 /* True when BB is a header of the inner loop. */ 1041 /* True when BB is a header of the inner loop. */
1032 static inline bool 1042 static inline bool
1035 struct loop *inner_loop; 1045 struct loop *inner_loop;
1036 1046
1037 if (!current_loop_nest) 1047 if (!current_loop_nest)
1038 return false; 1048 return false;
1039 1049
1040 if (bb == EXIT_BLOCK_PTR) 1050 if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
1041 return false; 1051 return false;
1042 1052
1043 inner_loop = bb->loop_father; 1053 inner_loop = bb->loop_father;
1044 if (inner_loop == current_loop_nest) 1054 if (inner_loop == current_loop_nest)
1045 return false; 1055 return false;
1055 1065
1056 return false; 1066 return false;
1057 } 1067 }
1058 1068
1059 /* Return exit edges of LOOP, filtering out edges with the same dest bb. */ 1069 /* Return exit edges of LOOP, filtering out edges with the same dest bb. */
1060 static inline VEC (edge, heap) * 1070 static inline vec<edge>
1061 get_loop_exit_edges_unique_dests (const struct loop *loop) 1071 get_loop_exit_edges_unique_dests (const struct loop *loop)
1062 { 1072 {
1063 VEC (edge, heap) *edges = NULL; 1073 vec<edge> edges = vNULL;
1064 struct loop_exit *exit; 1074 struct loop_exit *exit;
1065 1075
1066 gcc_assert (loop->latch != EXIT_BLOCK_PTR 1076 gcc_assert (loop->latch != EXIT_BLOCK_PTR_FOR_FN (cfun)
1067 && current_loops->state & LOOPS_HAVE_RECORDED_EXITS); 1077 && current_loops->state & LOOPS_HAVE_RECORDED_EXITS);
1068 1078
1069 for (exit = loop->exits->next; exit->e; exit = exit->next) 1079 for (exit = loop->exits->next; exit->e; exit = exit->next)
1070 { 1080 {
1071 int i; 1081 int i;
1072 edge e; 1082 edge e;
1073 bool was_dest = false; 1083 bool was_dest = false;
1074 1084
1075 for (i = 0; VEC_iterate (edge, edges, i, e); i++) 1085 for (i = 0; edges.iterate (i, &e); i++)
1076 if (e->dest == exit->e->dest) 1086 if (e->dest == exit->e->dest)
1077 { 1087 {
1078 was_dest = true; 1088 was_dest = true;
1079 break; 1089 break;
1080 } 1090 }
1081 1091
1082 if (!was_dest) 1092 if (!was_dest)
1083 VEC_safe_push (edge, heap, edges, exit->e); 1093 edges.safe_push (exit->e);
1084 } 1094 }
1085 return edges; 1095 return edges;
1086 } 1096 }
1087 1097
1088 static bool 1098 static bool
1094 return true; 1104 return true;
1095 1105
1096 if (!INSN_NOP_P (first)) 1106 if (!INSN_NOP_P (first))
1097 return false; 1107 return false;
1098 1108
1099 if (bb == EXIT_BLOCK_PTR) 1109 if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun))
1100 return false; 1110 return false;
1101 1111
1102 last = sel_bb_end (bb); 1112 last = sel_bb_end (bb);
1103 if (first != last) 1113 if (first != last)
1104 return false; 1114 return false;
1109 /* Collect all loop exits recursively, skipping empty BBs between them. 1119 /* Collect all loop exits recursively, skipping empty BBs between them.
1110 E.g. if BB is a loop header which has several loop exits, 1120 E.g. if BB is a loop header which has several loop exits,
1111 traverse all of them and if any of them turns out to be another loop header 1121 traverse all of them and if any of them turns out to be another loop header
1112 (after skipping empty BBs), add its loop exits to the resulting vector 1122 (after skipping empty BBs), add its loop exits to the resulting vector
1113 as well. */ 1123 as well. */
1114 static inline VEC(edge, heap) * 1124 static inline vec<edge>
1115 get_all_loop_exits (basic_block bb) 1125 get_all_loop_exits (basic_block bb)
1116 { 1126 {
1117 VEC(edge, heap) *exits = NULL; 1127 vec<edge> exits = vNULL;
1118 1128
1119 /* If bb is empty, and we're skipping to loop exits, then 1129 /* If bb is empty, and we're skipping to loop exits, then
1120 consider bb as a possible gate to the inner loop now. */ 1130 consider bb as a possible gate to the inner loop now. */
1121 while (sel_bb_empty_or_nop_p (bb) 1131 while (sel_bb_empty_or_nop_p (bb)
1122 && in_current_region_p (bb)) 1132 && in_current_region_p (bb)
1133 && EDGE_COUNT (bb->succs) > 0)
1123 { 1134 {
1124 bb = single_succ (bb); 1135 bb = single_succ (bb);
1125 1136
1126 /* This empty block could only lead outside the region. */ 1137 /* This empty block could only lead outside the region. */
1127 gcc_assert (! in_current_region_p (bb)); 1138 gcc_assert (! in_current_region_p (bb));
1144 gcc_assert (this_loop != NULL); 1155 gcc_assert (this_loop != NULL);
1145 1156
1146 exits = get_loop_exit_edges_unique_dests (this_loop); 1157 exits = get_loop_exit_edges_unique_dests (this_loop);
1147 1158
1148 /* Traverse all loop headers. */ 1159 /* Traverse all loop headers. */
1149 for (i = 0; VEC_iterate (edge, exits, i, e); i++) 1160 for (i = 0; exits.iterate (i, &e); i++)
1150 if (in_current_region_p (e->dest) 1161 if (in_current_region_p (e->dest)
1151 || inner_loop_header_p (e->dest)) 1162 || inner_loop_header_p (e->dest))
1152 { 1163 {
1153 VEC(edge, heap) *next_exits = get_all_loop_exits (e->dest); 1164 vec<edge> next_exits = get_all_loop_exits (e->dest);
1154 1165
1155 if (next_exits) 1166 if (next_exits.exists ())
1156 { 1167 {
1157 int j; 1168 int j;
1158 edge ne; 1169 edge ne;
1159 1170
1160 /* Add all loop exits for the current edge into the 1171 /* Add all loop exits for the current edge into the
1161 resulting vector. */ 1172 resulting vector. */
1162 for (j = 0; VEC_iterate (edge, next_exits, j, ne); j++) 1173 for (j = 0; next_exits.iterate (j, &ne); j++)
1163 VEC_safe_push (edge, heap, exits, ne); 1174 exits.safe_push (ne);
1164 1175
1165 /* Remove the original edge. */ 1176 /* Remove the original edge. */
1166 VEC_ordered_remove (edge, exits, i); 1177 exits.ordered_remove (i);
1167 1178
1168 /* Decrease the loop counter so we won't skip anything. */ 1179 /* Decrease the loop counter so we won't skip anything. */
1169 i--; 1180 i--;
1170 continue; 1181 continue;
1171 } 1182 }
1212 i.e1 = NULL; 1223 i.e1 = NULL;
1213 i.e2 = NULL; 1224 i.e2 = NULL;
1214 i.bb = bb; 1225 i.bb = bb;
1215 i.current_flags = 0; 1226 i.current_flags = 0;
1216 i.current_exit = -1; 1227 i.current_exit = -1;
1217 i.loop_exits = NULL; 1228 i.loop_exits.create (0);
1218 1229
1219 if (bb != EXIT_BLOCK_PTR && BB_END (bb) != insn) 1230 if (bb != EXIT_BLOCK_PTR_FOR_FN (cfun) && BB_END (bb) != insn)
1220 { 1231 {
1221 i.bb_end = false; 1232 i.bb_end = false;
1222 1233
1223 /* Avoid 'uninitialized' warning. */ 1234 /* Avoid 'uninitialized' warning. */
1224 i.ei.index = 0; 1235 i.ei.index = 0;
1225 i.ei.container = NULL; 1236 i.ei.container = 0;
1226 } 1237 }
1227 else 1238 else
1228 { 1239 {
1229 i.ei = ei_start (bb->succs); 1240 i.ei = ei_start (bb->succs);
1230 i.bb_end = true; 1241 i.bb_end = true;
1232 1243
1233 return i; 1244 return i;
1234 } 1245 }
1235 1246
1236 static inline bool 1247 static inline bool
1237 _succ_iter_cond (succ_iterator *ip, rtx *succp, rtx insn, 1248 _succ_iter_cond (succ_iterator *ip, insn_t *succp, insn_t insn,
1238 bool check (edge, succ_iterator *)) 1249 bool check (edge, succ_iterator *))
1239 { 1250 {
1240 if (!ip->bb_end) 1251 if (!ip->bb_end)
1241 { 1252 {
1242 /* When we're in a middle of a basic block, return 1253 /* When we're in a middle of a basic block, return
1253 while (1) 1264 while (1)
1254 { 1265 {
1255 edge e_tmp = NULL; 1266 edge e_tmp = NULL;
1256 1267
1257 /* First, try loop exits, if we have them. */ 1268 /* First, try loop exits, if we have them. */
1258 if (ip->loop_exits) 1269 if (ip->loop_exits.exists ())
1259 { 1270 {
1260 do 1271 do
1261 { 1272 {
1262 VEC_iterate (edge, ip->loop_exits, 1273 ip->loop_exits.iterate (ip->current_exit, &e_tmp);
1263 ip->current_exit, e_tmp);
1264 ip->current_exit++; 1274 ip->current_exit++;
1265 } 1275 }
1266 while (e_tmp && !check (e_tmp, ip)); 1276 while (e_tmp && !check (e_tmp, ip));
1267 1277
1268 if (!e_tmp) 1278 if (!e_tmp)
1269 VEC_free (edge, heap, ip->loop_exits); 1279 ip->loop_exits.release ();
1270 } 1280 }
1271 1281
1272 /* If we have found a successor, then great. */ 1282 /* If we have found a successor, then great. */
1273 if (e_tmp) 1283 if (e_tmp)
1274 { 1284 {
1289 < BLOCK_TO_BB (bb->index))) 1299 < BLOCK_TO_BB (bb->index)))
1290 { 1300 {
1291 /* Get all loop exits recursively. */ 1301 /* Get all loop exits recursively. */
1292 ip->loop_exits = get_all_loop_exits (bb); 1302 ip->loop_exits = get_all_loop_exits (bb);
1293 1303
1294 if (ip->loop_exits) 1304 if (ip->loop_exits.exists ())
1295 { 1305 {
1296 ip->current_exit = 0; 1306 ip->current_exit = 0;
1297 /* Move the iterator now, because we won't do 1307 /* Move the iterator now, because we won't do
1298 succ_iter_next until loop exits will end. */ 1308 succ_iter_next until loop exits will end. */
1299 ei_next (&(ip->ei)); 1309 ei_next (&(ip->ei));
1308 ei_next (&(ip->ei)); 1318 ei_next (&(ip->ei));
1309 } 1319 }
1310 1320
1311 /* If loop_exits are non null, we have found an inner loop; 1321 /* If loop_exits are non null, we have found an inner loop;
1312 do one more iteration to fetch an edge from these exits. */ 1322 do one more iteration to fetch an edge from these exits. */
1313 if (ip->loop_exits) 1323 if (ip->loop_exits.exists ())
1314 continue; 1324 continue;
1315 1325
1316 /* Otherwise, we've found an edge in a usual way. Break now. */ 1326 /* Otherwise, we've found an edge in a usual way. Break now. */
1317 break; 1327 break;
1318 } 1328 }
1319 1329
1320 if (ip->e1) 1330 if (ip->e1)
1321 { 1331 {
1322 basic_block bb = ip->e2->dest; 1332 basic_block bb = ip->e2->dest;
1323 1333
1324 if (bb == EXIT_BLOCK_PTR || bb == after_recovery) 1334 if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun) || bb == after_recovery)
1325 *succp = exit_insn; 1335 *succp = exit_insn;
1326 else 1336 else
1327 { 1337 {
1328 *succp = sel_bb_head (bb); 1338 *succp = sel_bb_head (bb);
1329 1339
1342 static inline void 1352 static inline void
1343 _succ_iter_next (succ_iterator *ip) 1353 _succ_iter_next (succ_iterator *ip)
1344 { 1354 {
1345 gcc_assert (!ip->e2 || ip->e1); 1355 gcc_assert (!ip->e2 || ip->e1);
1346 1356
1347 if (ip->bb_end && ip->e1 && !ip->loop_exits) 1357 if (ip->bb_end && ip->e1 && !ip->loop_exits.exists ())
1348 ei_next (&(ip->ei)); 1358 ei_next (&(ip->ei));
1349 } 1359 }
1350 1360
1351 /* Returns true when E1 is an eligible successor edge, possibly skipping 1361 /* Returns true when E1 is an eligible successor edge, possibly skipping
1352 empty blocks. When E2P is not null, the resulting edge is written there. 1362 empty blocks. When E2P is not null, the resulting edge is written there.
1541 extern void merge_expr_data (expr_t, expr_t, insn_t); 1551 extern void merge_expr_data (expr_t, expr_t, insn_t);
1542 extern void merge_expr (expr_t, expr_t, insn_t); 1552 extern void merge_expr (expr_t, expr_t, insn_t);
1543 extern void clear_expr (expr_t); 1553 extern void clear_expr (expr_t);
1544 extern unsigned expr_dest_regno (expr_t); 1554 extern unsigned expr_dest_regno (expr_t);
1545 extern rtx expr_dest_reg (expr_t); 1555 extern rtx expr_dest_reg (expr_t);
1546 extern int find_in_history_vect (VEC(expr_history_def, heap) *, 1556 extern int find_in_history_vect (vec<expr_history_def> ,
1547 rtx, vinsn_t, bool); 1557 rtx, vinsn_t, bool);
1548 extern void insert_in_history_vect (VEC(expr_history_def, heap) **, 1558 extern void insert_in_history_vect (vec<expr_history_def> *,
1549 unsigned, enum local_trans_type, 1559 unsigned, enum local_trans_type,
1550 vinsn_t, vinsn_t, ds_t); 1560 vinsn_t, vinsn_t, ds_t);
1551 extern void mark_unavailable_targets (av_set_t, av_set_t, regset); 1561 extern void mark_unavailable_targets (av_set_t, av_set_t, regset);
1552 extern int speculate_expr (expr_t, ds_t); 1562 extern int speculate_expr (expr_t, ds_t);
1553 1563
1563 extern void av_set_clear (av_set_t *); 1573 extern void av_set_clear (av_set_t *);
1564 extern void av_set_leave_one_nonspec (av_set_t *); 1574 extern void av_set_leave_one_nonspec (av_set_t *);
1565 extern expr_t av_set_element (av_set_t, int); 1575 extern expr_t av_set_element (av_set_t, int);
1566 extern void av_set_substract_cond_branches (av_set_t *); 1576 extern void av_set_substract_cond_branches (av_set_t *);
1567 extern void av_set_split_usefulness (av_set_t, int, int); 1577 extern void av_set_split_usefulness (av_set_t, int, int);
1568 extern void av_set_intersect (av_set_t *, av_set_t); 1578 extern void av_set_code_motion_filter (av_set_t *, av_set_t);
1569 1579
1570 extern void sel_save_haifa_priorities (void); 1580 extern void sel_save_haifa_priorities (void);
1571 1581
1572 extern void sel_init_global_and_expr (bb_vec_t); 1582 extern void sel_init_global_and_expr (bb_vec_t);
1573 extern void sel_finish_global_and_expr (void); 1583 extern void sel_finish_global_and_expr (void);
1574 1584
1575 extern regset compute_live (insn_t); 1585 extern regset compute_live (insn_t);
1586 extern bool register_unavailable_p (regset, rtx);
1576 1587
1577 /* Dependence analysis functions. */ 1588 /* Dependence analysis functions. */
1578 extern void sel_clear_has_dependence (void); 1589 extern void sel_clear_has_dependence (void);
1579 extern ds_t has_dependence_p (expr_t, insn_t, ds_t **); 1590 extern ds_t has_dependence_p (expr_t, insn_t, ds_t **);
1580 1591
1581 extern int tick_check_p (expr_t, deps_t, fence_t); 1592 extern int tick_check_p (expr_t, deps_t, fence_t);
1582 1593
1583 /* Functions to work with insns. */ 1594 /* Functions to work with insns. */
1584 extern bool lhs_of_insn_equals_to_dest_p (insn_t, rtx); 1595 extern bool lhs_of_insn_equals_to_dest_p (insn_t, rtx);
1585 extern bool insn_eligible_for_subst_p (insn_t); 1596 extern bool insn_eligible_for_subst_p (insn_t);
1586 extern void get_dest_and_mode (rtx, rtx *, enum machine_mode *); 1597 extern void get_dest_and_mode (rtx, rtx *, machine_mode *);
1587 1598
1588 extern bool bookkeeping_can_be_created_if_moved_through_p (insn_t); 1599 extern bool bookkeeping_can_be_created_if_moved_through_p (insn_t);
1589 extern bool sel_remove_insn (insn_t, bool, bool); 1600 extern bool sel_remove_insn (insn_t, bool, bool);
1590 extern bool bb_header_p (insn_t); 1601 extern bool bb_header_p (insn_t);
1591 extern void sel_init_invalid_data_sets (insn_t); 1602 extern void sel_init_invalid_data_sets (insn_t);
1592 extern bool insn_at_boundary_p (insn_t); 1603 extern bool insn_at_boundary_p (insn_t);
1593 1604
1594 /* Basic block and CFG functions. */ 1605 /* Basic block and CFG functions. */
1595 1606
1596 extern insn_t sel_bb_head (basic_block); 1607 extern rtx_insn *sel_bb_head (basic_block);
1597 extern bool sel_bb_head_p (insn_t); 1608 extern bool sel_bb_head_p (insn_t);
1598 extern insn_t sel_bb_end (basic_block); 1609 extern rtx_insn *sel_bb_end (basic_block);
1599 extern bool sel_bb_end_p (insn_t); 1610 extern bool sel_bb_end_p (insn_t);
1600 extern bool sel_bb_empty_p (basic_block); 1611 extern bool sel_bb_empty_p (basic_block);
1601 1612
1602 extern bool in_current_region_p (basic_block); 1613 extern bool in_current_region_p (basic_block);
1603 extern basic_block fallthru_bb_of_jump (rtx); 1614 extern basic_block fallthru_bb_of_jump (const rtx_insn *);
1604 1615
1605 extern void sel_init_bbs (bb_vec_t, basic_block); 1616 extern void sel_init_bbs (bb_vec_t);
1606 extern void sel_finish_bbs (void); 1617 extern void sel_finish_bbs (void);
1607 1618
1608 extern struct succs_info * compute_succs_info (insn_t, short); 1619 extern struct succs_info * compute_succs_info (insn_t, short);
1609 extern void free_succs_info (struct succs_info *); 1620 extern void free_succs_info (struct succs_info *);
1610 extern bool sel_insn_has_single_succ_p (insn_t, int); 1621 extern bool sel_insn_has_single_succ_p (insn_t, int);
1611 extern bool sel_num_cfg_preds_gt_1 (insn_t); 1622 extern bool sel_num_cfg_preds_gt_1 (insn_t);
1612 extern int get_seqno_by_preds (rtx); 1623 extern int get_seqno_by_preds (rtx_insn *);
1613 1624
1614 extern bool bb_ends_ebb_p (basic_block); 1625 extern bool bb_ends_ebb_p (basic_block);
1615 extern bool in_same_ebb_p (insn_t, insn_t); 1626 extern bool in_same_ebb_p (insn_t, insn_t);
1616 1627
1617 extern bool tidy_control_flow (basic_block, bool); 1628 extern bool tidy_control_flow (basic_block, bool);
1625 extern void sel_init_pipelining (void); 1636 extern void sel_init_pipelining (void);
1626 extern void sel_finish_pipelining (void); 1637 extern void sel_finish_pipelining (void);
1627 extern void sel_sched_region (int); 1638 extern void sel_sched_region (int);
1628 extern loop_p get_loop_nest_for_rgn (unsigned int); 1639 extern loop_p get_loop_nest_for_rgn (unsigned int);
1629 extern bool considered_for_pipelining_p (struct loop *); 1640 extern bool considered_for_pipelining_p (struct loop *);
1630 extern void make_region_from_loop_preheader (VEC(basic_block, heap) **); 1641 extern void make_region_from_loop_preheader (vec<basic_block> *&);
1631 extern void sel_add_loop_preheaders (void); 1642 extern void sel_add_loop_preheaders (bb_vec_t *);
1632 extern bool sel_is_loop_preheader_p (basic_block); 1643 extern bool sel_is_loop_preheader_p (basic_block);
1633 extern void clear_outdated_rtx_info (basic_block); 1644 extern void clear_outdated_rtx_info (basic_block);
1634 extern void free_data_sets (basic_block); 1645 extern void free_data_sets (basic_block);
1635 extern void exchange_data_sets (basic_block, basic_block); 1646 extern void exchange_data_sets (basic_block, basic_block);
1636 extern void copy_data_sets (basic_block, basic_block); 1647 extern void copy_data_sets (basic_block, basic_block);
1637 1648
1638 extern void sel_register_cfg_hooks (void); 1649 extern void sel_register_cfg_hooks (void);
1639 extern void sel_unregister_cfg_hooks (void); 1650 extern void sel_unregister_cfg_hooks (void);
1640 1651
1641 /* Expression transformation routines. */ 1652 /* Expression transformation routines. */
1642 extern rtx create_insn_rtx_from_pattern (rtx, rtx); 1653 extern rtx_insn *create_insn_rtx_from_pattern (rtx, rtx);
1643 extern vinsn_t create_vinsn_from_insn_rtx (rtx, bool); 1654 extern vinsn_t create_vinsn_from_insn_rtx (rtx_insn *, bool);
1644 extern rtx create_copy_of_insn_rtx (rtx); 1655 extern rtx_insn *create_copy_of_insn_rtx (rtx);
1645 extern void change_vinsn_in_expr (expr_t, vinsn_t); 1656 extern void change_vinsn_in_expr (expr_t, vinsn_t);
1646 1657
1647 /* Various initialization functions. */ 1658 /* Various initialization functions. */
1648 extern void init_lv_sets (void); 1659 extern void init_lv_sets (void);
1649 extern void free_lv_sets (void); 1660 extern void free_lv_sets (void);
1656 extern void sel_setup_sched_infos (void); 1667 extern void sel_setup_sched_infos (void);
1657 extern void alloc_sched_pools (void); 1668 extern void alloc_sched_pools (void);
1658 extern void free_sched_pools (void); 1669 extern void free_sched_pools (void);
1659 1670
1660 #endif /* GCC_SEL_SCHED_IR_H */ 1671 #endif /* GCC_SEL_SCHED_IR_H */
1661
1662
1663
1664
1665
1666
1667
1668