postreload-gcse.c (225736) | postreload-gcse.c (259269) |
---|---|
1/* Post reload partially redundant load elimination 2 Copyright (C) 2004, 2005 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free --- 183 unchanged lines hidden (view full) --- 192static struct expr *lookup_expr_in_table (rtx); 193static int dump_hash_table_entry (void **, void *); 194static void dump_hash_table (FILE *); 195 196/* Helpers for eliminate_partially_redundant_load. */ 197static bool reg_killed_on_edge (rtx, edge); 198static bool reg_used_on_edge (rtx, edge); 199 | 1/* Post reload partially redundant load elimination 2 Copyright (C) 2004, 2005 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free --- 183 unchanged lines hidden (view full) --- 192static struct expr *lookup_expr_in_table (rtx); 193static int dump_hash_table_entry (void **, void *); 194static void dump_hash_table (FILE *); 195 196/* Helpers for eliminate_partially_redundant_load. */ 197static bool reg_killed_on_edge (rtx, edge); 198static bool reg_used_on_edge (rtx, edge); 199 |
200static rtx reg_set_between_after_reload_p (rtx, rtx, rtx); 201static rtx reg_used_between_after_reload_p (rtx, rtx, rtx); | |
202static rtx get_avail_load_store_reg (rtx); 203 204static bool bb_has_well_behaved_predecessors (basic_block); 205static struct occr* get_bb_avail_insn (basic_block, struct occr *); 206static void hash_scan_set (rtx); 207static void compute_hash_table (void); 208 209/* The work horses of this pass. */ --- 255 unchanged lines hidden (view full) --- 465 if (htab_elements (expr_table) > 0) 466 { 467 fprintf (file, "\n\ntable entries:\n"); 468 htab_traverse (expr_table, dump_hash_table_entry, file); 469 } 470 fprintf (file, "\n"); 471} 472 | 200static rtx get_avail_load_store_reg (rtx); 201 202static bool bb_has_well_behaved_predecessors (basic_block); 203static struct occr* get_bb_avail_insn (basic_block, struct occr *); 204static void hash_scan_set (rtx); 205static void compute_hash_table (void); 206 207/* The work horses of this pass. */ --- 255 unchanged lines hidden (view full) --- 463 if (htab_elements (expr_table) > 0) 464 { 465 fprintf (file, "\n\ntable entries:\n"); 466 htab_traverse (expr_table, dump_hash_table_entry, file); 467 } 468 fprintf (file, "\n"); 469} 470 |
471/* Return true if register X is recorded as being set by an instruction 472 whose CUID is greater than the one given. */ |
|
473 | 473 |
474static bool 475reg_changed_after_insn_p (rtx x, int cuid) 476{ 477 unsigned int regno, end_regno; 478 479 regno = REGNO (x); 480 end_regno = END_HARD_REGNO (x); 481 do 482 if (reg_avail_info[regno] > cuid) 483 return true; 484 while (++regno < end_regno); 485 return false; 486} 487 |
|
474/* Return nonzero if the operands of expression X are unchanged 475 1) from the start of INSN's basic block up to but not including INSN 476 if AFTER_INSN is false, or 477 2) from INSN to the end of INSN's basic block if AFTER_INSN is true. */ 478 479static bool 480oprs_unchanged_p (rtx x, rtx insn, bool after_insn) 481{ --- 6 unchanged lines hidden (view full) --- 488 489 code = GET_CODE (x); 490 switch (code) 491 { 492 case REG: 493 /* We are called after register allocation. */ 494 gcc_assert (REGNO (x) < FIRST_PSEUDO_REGISTER); 495 if (after_insn) | 488/* Return nonzero if the operands of expression X are unchanged 489 1) from the start of INSN's basic block up to but not including INSN 490 if AFTER_INSN is false, or 491 2) from INSN to the end of INSN's basic block if AFTER_INSN is true. */ 492 493static bool 494oprs_unchanged_p (rtx x, rtx insn, bool after_insn) 495{ --- 6 unchanged lines hidden (view full) --- 502 503 code = GET_CODE (x); 504 switch (code) 505 { 506 case REG: 507 /* We are called after register allocation. */ 508 gcc_assert (REGNO (x) < FIRST_PSEUDO_REGISTER); 509 if (after_insn) |
496 /* If the last CUID setting the insn is less than the CUID of 497 INSN, then reg X is not changed in or after INSN. */ 498 return reg_avail_info[REGNO (x)] < INSN_CUID (insn); | 510 return !reg_changed_after_insn_p (x, INSN_CUID (insn) - 1); |
499 else | 511 else |
500 /* Reg X is not set before INSN in the current basic block if 501 we have not yet recorded the CUID of an insn that touches 502 the reg. */ 503 return reg_avail_info[REGNO (x)] == 0; | 512 return !reg_changed_after_insn_p (x, 0); |
504 505 case MEM: 506 if (load_killed_in_block_p (INSN_CUID (insn), x, after_insn)) 507 return 0; 508 else 509 return oprs_unchanged_p (XEXP (x, 0), insn, after_insn); 510 511 case PC: --- 200 unchanged lines hidden (view full) --- 712 /* Also record autoincremented REGs for this insn as changed. */ 713 for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 714 if (REG_NOTE_KIND (note) == REG_INC) 715 record_last_reg_set_info (insn, REGNO (XEXP (note, 0))); 716 717 /* Finally, if this is a call, record all call clobbers. */ 718 if (CALL_P (insn)) 719 { | 513 514 case MEM: 515 if (load_killed_in_block_p (INSN_CUID (insn), x, after_insn)) 516 return 0; 517 else 518 return oprs_unchanged_p (XEXP (x, 0), insn, after_insn); 519 520 case PC: --- 200 unchanged lines hidden (view full) --- 721 /* Also record autoincremented REGs for this insn as changed. */ 722 for (note = REG_NOTES (insn); note; note = XEXP (note, 1)) 723 if (REG_NOTE_KIND (note) == REG_INC) 724 record_last_reg_set_info (insn, REGNO (XEXP (note, 0))); 725 726 /* Finally, if this is a call, record all call clobbers. */ 727 if (CALL_P (insn)) 728 { |
720 unsigned int regno; | 729 unsigned int regno, end_regno; 730 rtx link, x; |
721 722 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 723 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)) 724 record_last_reg_set_info (insn, regno); 725 | 731 732 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 733 if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)) 734 record_last_reg_set_info (insn, regno); 735 |
736 for (link = CALL_INSN_FUNCTION_USAGE (insn); link; link = XEXP (link, 1)) 737 if (GET_CODE (XEXP (link, 0)) == CLOBBER) 738 { 739 x = XEXP (XEXP (link, 0), 0); 740 if (REG_P (x)) 741 { 742 gcc_assert (HARD_REGISTER_P (x)); 743 regno = REGNO (x); 744 end_regno = END_HARD_REGNO (x); 745 do 746 record_last_reg_set_info (insn, regno); 747 while (++regno < end_regno); 748 } 749 } 750 |
|
726 if (! CONST_OR_PURE_CALL_P (insn)) 727 record_last_mem_set_info (insn); 728 } 729} 730 731 732/* Scan the pattern of INSN and add an entry to the hash TABLE. 733 After reload we are interested in loads/stores only. */ --- 117 unchanged lines hidden (view full) --- 851 852 for (insn = e->insns.r; insn; insn = NEXT_INSN (insn)) 853 if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn))) 854 return true; 855 856 return false; 857} 858 | 751 if (! CONST_OR_PURE_CALL_P (insn)) 752 record_last_mem_set_info (insn); 753 } 754} 755 756 757/* Scan the pattern of INSN and add an entry to the hash TABLE. 758 After reload we are interested in loads/stores only. */ --- 117 unchanged lines hidden (view full) --- 876 877 for (insn = e->insns.r; insn; insn = NEXT_INSN (insn)) 878 if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn))) 879 return true; 880 881 return false; 882} 883 |
859 860/* Return the insn that sets register REG or clobbers it in between 861 FROM_INSN and TO_INSN (exclusive of those two). 862 Just like reg_set_between but for hard registers and not pseudos. */ 863 864static rtx 865reg_set_between_after_reload_p (rtx reg, rtx from_insn, rtx to_insn) 866{ 867 rtx insn; 868 869 /* We are called after register allocation. */ 870 gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER); 871 872 if (from_insn == to_insn) 873 return NULL_RTX; 874 875 for (insn = NEXT_INSN (from_insn); 876 insn != to_insn; 877 insn = NEXT_INSN (insn)) 878 if (INSN_P (insn)) 879 { 880 if (set_of (reg, insn) != NULL_RTX) 881 return insn; 882 if ((CALL_P (insn) 883 && call_used_regs[REGNO (reg)]) 884 || find_reg_fusage (insn, CLOBBER, reg)) 885 return insn; 886 887 if (FIND_REG_INC_NOTE (insn, reg)) 888 return insn; 889 } 890 891 return NULL_RTX; 892} 893 894/* Return the insn that uses register REG in between FROM_INSN and TO_INSN 895 (exclusive of those two). Similar to reg_used_between but for hard 896 registers and not pseudos. */ 897 898static rtx 899reg_used_between_after_reload_p (rtx reg, rtx from_insn, rtx to_insn) 900{ 901 rtx insn; 902 903 /* We are called after register allocation. */ 904 gcc_assert (REG_P (reg) && REGNO (reg) < FIRST_PSEUDO_REGISTER); 905 906 if (from_insn == to_insn) 907 return NULL_RTX; 908 909 for (insn = NEXT_INSN (from_insn); 910 insn != to_insn; 911 insn = NEXT_INSN (insn)) 912 if (INSN_P (insn)) 913 { 914 if (reg_overlap_mentioned_p (reg, PATTERN (insn)) 915 || (CALL_P (insn) 916 && call_used_regs[REGNO (reg)]) 917 || find_reg_fusage (insn, USE, reg) 918 || find_reg_fusage (insn, CLOBBER, reg)) 919 return insn; 920 921 if (FIND_REG_INC_NOTE (insn, reg)) 922 return insn; 923 } 924 925 return NULL_RTX; 926} 927 928/* Return true if REG is used, set, or killed between the beginning of 929 basic block BB and UP_TO_INSN. Caches the result in reg_avail_info. */ 930 931static bool 932reg_set_or_used_since_bb_start (rtx reg, basic_block bb, rtx up_to_insn) 933{ 934 rtx insn, start = PREV_INSN (BB_HEAD (bb)); 935 936 if (reg_avail_info[REGNO (reg)] != 0) 937 return true; 938 939 insn = reg_used_between_after_reload_p (reg, start, up_to_insn); 940 if (! insn) 941 insn = reg_set_between_after_reload_p (reg, start, up_to_insn); 942 943 if (insn) 944 reg_avail_info[REGNO (reg)] = INSN_CUID (insn); 945 946 return insn != NULL_RTX; 947} 948 | |
949/* Return the loaded/stored register of a load/store instruction. */ 950 951static rtx 952get_avail_load_store_reg (rtx insn) 953{ 954 if (REG_P (SET_DEST (PATTERN (insn)))) 955 /* A load. */ 956 return SET_DEST(PATTERN(insn)); --- 75 unchanged lines hidden (view full) --- 1032 gcov_type not_ok_count = 0; 1033 basic_block pred_bb; 1034 1035 pat = PATTERN (insn); 1036 dest = SET_DEST (pat); 1037 1038 /* Check that the loaded register is not used, set, or killed from the 1039 beginning of the block. */ | 884/* Return the loaded/stored register of a load/store instruction. */ 885 886static rtx 887get_avail_load_store_reg (rtx insn) 888{ 889 if (REG_P (SET_DEST (PATTERN (insn)))) 890 /* A load. */ 891 return SET_DEST(PATTERN(insn)); --- 75 unchanged lines hidden (view full) --- 967 gcov_type not_ok_count = 0; 968 basic_block pred_bb; 969 970 pat = PATTERN (insn); 971 dest = SET_DEST (pat); 972 973 /* Check that the loaded register is not used, set, or killed from the 974 beginning of the block. */ |
1040 if (reg_set_or_used_since_bb_start (dest, bb, insn)) | 975 if (reg_changed_after_insn_p (dest, 0) 976 || reg_used_between_p (dest, PREV_INSN (BB_HEAD (bb)), insn)) |
1041 return; 1042 1043 /* Check potential for replacing load with copy for predecessors. */ 1044 FOR_EACH_EDGE (pred, ei, bb->preds) 1045 { 1046 rtx next_pred_bb_end; 1047 1048 avail_insn = NULL_RTX; --- 14 unchanged lines hidden (view full) --- 1063 copy_rtx (avail_reg))); 1064 if (! constrain_operands (1) 1065 || reg_killed_on_edge (avail_reg, pred) 1066 || reg_used_on_edge (dest, pred)) 1067 { 1068 avail_insn = NULL; 1069 continue; 1070 } | 977 return; 978 979 /* Check potential for replacing load with copy for predecessors. */ 980 FOR_EACH_EDGE (pred, ei, bb->preds) 981 { 982 rtx next_pred_bb_end; 983 984 avail_insn = NULL_RTX; --- 14 unchanged lines hidden (view full) --- 999 copy_rtx (avail_reg))); 1000 if (! constrain_operands (1) 1001 || reg_killed_on_edge (avail_reg, pred) 1002 || reg_used_on_edge (dest, pred)) 1003 { 1004 avail_insn = NULL; 1005 continue; 1006 } |
1071 if (! reg_set_between_after_reload_p (avail_reg, avail_insn, 1072 next_pred_bb_end)) | 1007 if (!reg_set_between_p (avail_reg, avail_insn, next_pred_bb_end)) |
1073 /* AVAIL_INSN remains non-null. */ 1074 break; 1075 else 1076 avail_insn = NULL; 1077 } 1078 1079 if (EDGE_CRITICAL_P (pred)) 1080 critical_count += pred->count; --- 314 unchanged lines hidden --- | 1008 /* AVAIL_INSN remains non-null. */ 1009 break; 1010 else 1011 avail_insn = NULL; 1012 } 1013 1014 if (EDGE_CRITICAL_P (pred)) 1015 critical_count += pred->count; --- 314 unchanged lines hidden --- |