Deleted Added
full compact
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 ---