diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/loop-doloop.c | 52 |
2 files changed, 60 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f5ba8f02..790662511 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-01-14 Richard Henderson <rth@redhat.com> + + PR rtl-opt/69014 + * loop-doloop.c (record_reg_sets): New. + (doloop_optimize): Reject the transform if the sequence + clobbers registers live at the end of the loop block. + (doloop_optimize_loops): Enable df_live if needed. + 2016-01-14 Michael Meissner <meissner@linux.vnet.ibm.com> * config/rs6000/rs6000-builtin.def: Revert 2016-01-13 change. diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c index 157de49..940c966 100644 --- a/gcc/loop-doloop.c +++ b/gcc/loop-doloop.c @@ -34,6 +34,8 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "dumpfile.h" #include "loop-unroll.h" +#include "regs.h" +#include "df.h" /* This module is used to modify loops with a determinable number of iterations to use special low-overhead looping instructions. @@ -573,6 +575,27 @@ doloop_modify (struct loop *loop, struct niter_desc *desc, } } +/* Called through note_stores. */ + +static void +record_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data) +{ + bitmap mod = (bitmap)data; + if (REG_P (x)) + { + unsigned int regno = REGNO (x); + if (HARD_REGISTER_P (x)) + { + unsigned int end_regno = end_hard_regno (GET_MODE (x), regno); + do + bitmap_set_bit (mod, regno); + while (++regno < end_regno); + } + else + bitmap_set_bit (mod, regno); + } +} + /* Process loop described by LOOP validating that the loop is suitable for conversion to use a low overhead looping instruction, replacing the jump insn where suitable. Returns true if the loop was successfully @@ -706,6 +729,26 @@ doloop_optimize (struct loop *loop) return false; } + /* Ensure that the new sequence doesn't clobber a register that + is live at the end of the block. */ + { + bitmap modified = BITMAP_ALLOC (NULL); + + for (rtx_insn *i = doloop_seq; i != NULL; i = NEXT_INSN (i)) + note_stores (PATTERN (i), record_reg_sets, modified); + + basic_block loop_end = desc->out_edge->src; + bool fail = bitmap_intersect_p (df_get_live_out (loop_end), modified); + BITMAP_FREE (modified); + + if (fail) + { + if (dump_file) + fprintf (dump_file, "Doloop: doloop pattern clobbers live out\n"); + return false; + } + } + doloop_modify (loop, desc, doloop_seq, condition, count); return true; } @@ -717,11 +760,20 @@ doloop_optimize_loops (void) { struct loop *loop; + if (optimize == 1) + { + df_live_add_problem (); + df_live_set_all_dirty (); + } + FOR_EACH_LOOP (loop, 0) { doloop_optimize (loop); } + if (optimize == 1) + df_remove_problem (df_live); + iv_analysis_done (); checking_verify_loop_structure (); |