diff options
author | Bernd Schmidt <bernds@cygnus.co.uk> | 1999-11-23 12:10:36 +0000 |
---|---|---|
committer | Bernd Schmidt <crux@gcc.gnu.org> | 1999-11-23 12:10:36 +0000 |
commit | c29f60c03cc219571c8c45ff8bb1b9b04efec478 (patch) | |
tree | 75db5dcb11714d1d5aa0e60c25cd0a38b56c11d8 /gcc | |
parent | 429d7c746fa51cbe5c4c5a096aa8952d59b63cd8 (diff) | |
download | gcc-c29f60c03cc219571c8c45ff8bb1b9b04efec478.zip gcc-c29f60c03cc219571c8c45ff8bb1b9b04efec478.tar.gz gcc-c29f60c03cc219571c8c45ff8bb1b9b04efec478.tar.bz2 |
Copy propagation for hoisted mems in loop.c.
From-SVN: r30638
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/Makefile.in | 2 | ||||
-rw-r--r-- | gcc/loop.c | 114 |
3 files changed, 120 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7d17085..237bf77 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +1999-11-23 Bernd Schmidt <bernds@cygnus.co.uk> + + * loop.c: Include "basic-block.h". + (try_copy_prop, replace_loop_reg): New functions. + (load_mems): Detect registers that just hold copies of the hoisted + mem, and call try_copy_prop to eliminate them. + * Makefile.in (loop.o): Update dependencies. + Tue Nov 23 01:03:29 1999 Hans-Peter Nilsson <hp@axis.com> * Makefile.in (gencheck.o): Depend on gencheck.h. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 710b411..771c22c 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1551,7 +1551,7 @@ profile.o : profile.c $(CONFIG_H) system.h $(RTL_H) flags.h insn-flags.h \ ggc.h loop.o : loop.c $(CONFIG_H) system.h $(RTL_H) flags.h loop.h insn-config.h \ insn-flags.h $(REGS_H) hard-reg-set.h $(RECOG_H) $(EXPR_H) real.h \ - function.h toplev.h varray.h except.h + $(BASIC_BLOCK_H) function.h toplev.h varray.h except.h unroll.o : unroll.c $(CONFIG_H) system.h $(RTL_H) insn-config.h function.h \ integrate.h $(REGS_H) $(RECOG_H) flags.h $(EXPR_H) loop.h toplev.h varray.h flow.o : flow.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h insn-config.h \ @@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA. */ #include "obstack.h" #include "function.h" #include "expr.h" +#include "basic-block.h" #include "insn-config.h" #include "insn-flags.h" #include "regs.h" @@ -337,6 +338,8 @@ static void load_mems_and_recount_loop_regs_set PROTO((rtx, rtx, rtx, static void load_mems PROTO((rtx, rtx, rtx, rtx)); static int insert_loop_mem PROTO((rtx *, void *)); static int replace_loop_mem PROTO((rtx *, void *)); +static int replace_loop_reg PROTO((rtx *, void *)); +static void try_copy_prop PROTO((rtx, rtx, rtx, rtx, int)); static int replace_label PROTO((rtx *, void *)); typedef struct rtx_and_int { @@ -9717,6 +9720,7 @@ load_mems (scan_start, end, loop_top, start) rtx end_label = NULL_RTX; /* Nonzero if the next instruction may never be executed. */ int next_maybe_never = 0; + int last_max_reg = max_reg_num (); if (loop_mems_idx == 0) return; @@ -9756,6 +9760,7 @@ load_mems (scan_start, end, loop_top, start) /* Actually move the MEMs. */ for (i = 0; i < loop_mems_idx; ++i) { + regset_head copies; int written = 0; rtx reg; rtx mem = loop_mems[i].mem; @@ -9817,6 +9822,8 @@ load_mems (scan_start, end, loop_top, start) loop, but later discovered that we could not. */ continue; + INIT_REG_SET (&copies); + /* Allocate a pseudo for this MEM. We set REG_USERVAR_P in order to keep scan_loop from moving stores to this MEM out of the loop just because this REG is neither a @@ -9827,14 +9834,37 @@ load_mems (scan_start, end, loop_top, start) /* Now, replace all references to the MEM with the corresponding pesudos. */ + maybe_never = 0; for (p = next_insn_in_loop (scan_start, scan_start, end, loop_top); p != NULL_RTX; p = next_insn_in_loop (p, scan_start, end, loop_top)) { rtx_and_int ri; - ri.r = p; - ri.i = i; - for_each_rtx (&p, replace_loop_mem, &ri); + rtx set; + + if (GET_RTX_CLASS (GET_CODE (p)) == 'i') + { + /* See if this copies the mem into a register that isn't + modified afterwards. We'll try to do copy propagation + a little further on. */ + set = single_set (p); + if (set + /* @@@ This test is _way_ too conservative. */ + && ! maybe_never + && GET_CODE (SET_DEST (set)) == REG + && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER + && REGNO (SET_DEST (set)) < last_max_reg + && VARRAY_INT (n_times_set, REGNO (SET_DEST (set))) == 1 + && rtx_equal_p (SET_SRC (set), loop_mems[i].mem)) + SET_REGNO_REG_SET (&copies, REGNO (SET_DEST (set))); + ri.r = p; + ri.i = i; + for_each_rtx (&p, replace_loop_mem, &ri); + } + + if (GET_CODE (p) == CODE_LABEL + || GET_CODE (p) == JUMP_INSN) + maybe_never = 1; } if (! apply_change_group ()) @@ -9842,6 +9872,7 @@ load_mems (scan_start, end, loop_top, start) loop_mems[i].optimize = 0; else { + int j; rtx set; /* Load the memory immediately before START, which is @@ -9874,6 +9905,16 @@ load_mems (scan_start, end, loop_top, start) print_rtl (loop_dump_stream, mem); fputc ('\n', loop_dump_stream); } + + /* Attempt a bit of copy propagation. This helps untangle the + data flow, and enables {basic,general}_induction_var to find + more bivs/givs. */ + EXECUTE_IF_SET_IN_REG_SET + (&copies, FIRST_PSEUDO_REGISTER, j, + { + try_copy_prop (scan_start, loop_top, end, loop_mems[i].reg, j); + }); + CLEAR_REG_SET (&copies); } } @@ -9901,6 +9942,51 @@ load_mems (scan_start, end, loop_top, start) } } +/* Try to replace every occurrence of pseudo REGNO with REPLACEMENT. + There must be exactly one insn that sets this pseudo; it will be + deleted if all replacements succeed and we can prove that the register + is not used after the loop. + The arguments SCAN_START, LOOP_TOP and END are as in load_mems. */ +static void +try_copy_prop (scan_start, loop_top, end, replacement, regno) + rtx scan_start, loop_top, end, replacement; + int regno; +{ + rtx init_insn = 0; + rtx insn; + for (insn = next_insn_in_loop (scan_start, scan_start, end, loop_top); + insn != NULL_RTX; + insn = next_insn_in_loop (insn, scan_start, end, loop_top)) + { + rtx set; + rtx array[3] = { regno_reg_rtx[regno], replacement, insn }; + if (GET_RTX_CLASS (GET_CODE (insn)) != 'i') + continue; + set = single_set (insn); + if (set + && GET_CODE (SET_DEST (set)) == REG + && REGNO (SET_DEST (set)) == regno) + { + if (init_insn) + abort (); + init_insn = insn; + } + for_each_rtx (&insn, replace_loop_reg, array); + } + if (! init_insn) + abort (); + if (apply_change_group ()) + { + if (uid_luid[REGNO_LAST_UID (regno)] < INSN_LUID (end)) + { + PUT_CODE (init_insn, NOTE); + NOTE_LINE_NUMBER (init_insn) = NOTE_INSN_DELETED; + } + if (loop_dump_stream) + fprintf (loop_dump_stream, " Replaced reg %d.\n", regno); + } +} + /* Replace MEM with its associated pseudo register. This function is called from load_mems via for_each_rtx. DATA is actually an rtx_and_int * describing the instruction currently being scanned @@ -9949,6 +10035,28 @@ replace_loop_mem (mem, data) return 0; } +/* Replace one register with another. Called through for_each_rtx; PX points + to the rtx being scanned. DATA is actually an array of three rtx's; the + first one is the one to be replaced, and the second one the replacement. + The third one is the current insn. */ + +static int +replace_loop_reg (px, data) + rtx *px; + void *data; +{ + rtx x = *px; + rtx *array = (rtx *)data; + + if (x == NULL_RTX) + return 0; + + if (x == array[0]) + validate_change (array[2], px, array[1], 1); + + return 0; +} + /* Replace occurrences of the old exit label for the loop with the new one. DATA is an rtx_pair containing the old and new labels, respectively. */ |