From 2407343c3da5e8dc3aee56ab3b7ba168de432973 Mon Sep 17 00:00:00 2001 From: Joern Rennecke Date: Tue, 16 Oct 2012 16:11:00 +0000 Subject: [PATCH] loop-doloop.c (doloop_modify): Pass doloop_end pattern to gen_doloop_begin. * loop-doloop.c (doloop_modify): Pass doloop_end pattern to gen_doloop_begin. (doloop_optimize): Pass flag to indicate if loop is entered at top to gen_doloop_end. * config/arm/thumb2.md (doloop_end): Accept extra operand. * config/bfin/bfin.md (doloop_end): Likewise. * config/c6x/c6x.md (doloop_end): Likewise. * config/ia64/ia64.md (doloop_end): Likewise. * config/mep/mep.md (doloop_begin, doloop_end): Likewise. * config/rs6000/rs6000.md (doloop_end): Likewise. * config/s390/s390.md (doloop_end): Likewise. * config/sh/sh.md (doloop_end): Likewise. * config/spu/spu.md (doloop_end): Likewise. * config/tilegx/tilegx.md (doloop_end): Likewise. * config/tilepro/tilepro.md (doloop_end): Likewise. * doc/md.texi (doloop_end): Document new operand. * basic-block.h (contains_no_active_insn_p): Declare. * cfgrtl.c (contains_no_active_insn_p): New function, factored out of ... (forwarder_block_p): ... here. From-SVN: r192505 --- gcc/ChangeLog | 23 +++++++++++++++++++++++ gcc/basic-block.h | 1 + gcc/cfgrtl.c | 29 ++++++++++++++++++++--------- gcc/config/arm/thumb2.md | 3 ++- gcc/config/bfin/bfin.md | 4 +++- gcc/config/c6x/c6x.md | 4 +++- gcc/config/ia64/ia64.md | 3 ++- gcc/config/mep/mep.md | 6 ++++-- gcc/config/rs6000/rs6000.md | 3 ++- gcc/config/s390/s390.md | 3 ++- gcc/config/sh/sh.md | 5 ++++- gcc/config/spu/spu.md | 3 ++- gcc/config/tilegx/tilegx.md | 3 ++- gcc/config/tilepro/tilepro.md | 3 ++- gcc/doc/md.texi | 4 +++- gcc/loop-doloop.c | 17 +++++++++++++---- 16 files changed, 88 insertions(+), 26 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7542474a53e..0b14270ee51 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2012-10-16 Joern Rennecke + + * loop-doloop.c (doloop_modify): Pass doloop_end pattern to + gen_doloop_begin. + (doloop_optimize): Pass flag to indicate if loop is entered at top + to gen_doloop_end. + * config/arm/thumb2.md (doloop_end): Accept extra operand. + * config/bfin/bfin.md (doloop_end): Likewise. + * config/c6x/c6x.md (doloop_end): Likewise. + * config/ia64/ia64.md (doloop_end): Likewise. + * config/mep/mep.md (doloop_begin, doloop_end): Likewise. + * config/rs6000/rs6000.md (doloop_end): Likewise. + * config/s390/s390.md (doloop_end): Likewise. + * config/sh/sh.md (doloop_end): Likewise. + * config/spu/spu.md (doloop_end): Likewise. + * config/tilegx/tilegx.md (doloop_end): Likewise. + * config/tilepro/tilepro.md (doloop_end): Likewise. + * doc/md.texi (doloop_end): Document new operand. + * basic-block.h (contains_no_active_insn_p): Declare. + * cfgrtl.c (contains_no_active_insn_p): New function, factored + out of ... + (forwarder_block_p): ... here. + 2012-10-16 Manuel López-Ibáñez PR c/53063 diff --git a/gcc/basic-block.h b/gcc/basic-block.h index 61351fb248d..d9bd3b7e550 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -802,6 +802,7 @@ extern bool purge_all_dead_edges (void); extern bool purge_dead_edges (basic_block); extern bool fixup_abnormal_edges (void); extern basic_block force_nonfallthru_and_redirect (edge, basic_block, rtx); +extern bool contains_no_active_insn_p (const_basic_block); extern bool forwarder_block_p (const_basic_block); extern bool can_fallthru (basic_block, basic_block); diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index 1b578d7feeb..b58562fcc5f 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -541,10 +541,9 @@ flow_active_insn_p (const_rtx insn) /* Return true if the block has no effect and only forwards control flow to its single destination. */ -/* FIXME: Make this a cfg hook. */ bool -forwarder_block_p (const_basic_block bb) +contains_no_active_insn_p (const_basic_block bb) { rtx insn; @@ -552,6 +551,24 @@ forwarder_block_p (const_basic_block bb) || !single_succ_p (bb)) return false; + for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn)) + if (INSN_P (insn) && flow_active_insn_p (insn)) + return false; + + return (!INSN_P (insn) + || (JUMP_P (insn) && simplejump_p (insn)) + || !flow_active_insn_p (insn)); +} + +/* Likewise, but protect loop latches, headers and preheaders. */ +/* FIXME: Make this a cfg hook. */ + +bool +forwarder_block_p (const_basic_block bb) +{ + if (!contains_no_active_insn_p (bb)) + return false; + /* Protect loop latches, headers and preheaders. */ if (current_loops) { @@ -563,13 +580,7 @@ forwarder_block_p (const_basic_block bb) return false; } - for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn)) - if (INSN_P (insn) && flow_active_insn_p (insn)) - return false; - - return (!INSN_P (insn) - || (JUMP_P (insn) && simplejump_p (insn)) - || !flow_active_insn_p (insn)); + return true; } /* Return nonzero if we can reach target from src by falling through. */ diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md index 57d1539ee3d..a5302f479f5 100644 --- a/gcc/config/arm/thumb2.md +++ b/gcc/config/arm/thumb2.md @@ -996,7 +996,8 @@ (use (match_operand 1 "" "")) ; iterations; zero if unknown (use (match_operand 2 "" "")) ; max iterations (use (match_operand 3 "" "")) ; loop level - (use (match_operand 4 "" ""))] ; label + (use (match_operand 4 "" "")) ; label + (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0 "TARGET_32BIT" " { diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 1774d3adff6..63ad1755020 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -1933,6 +1933,7 @@ ; operand 2 is the maximum number of loop iterations ; operand 3 is the number of levels of enclosed loops ; operand 4 is the label to jump to at the top of the loop +; operand 5 indicates if the loop is entered at the top (define_expand "doloop_end" [(parallel [(set (pc) (if_then_else (ne (match_operand:SI 0 "" "") @@ -1943,7 +1944,7 @@ (plus:SI (match_dup 0) (const_int -1))) (unspec [(const_int 0)] UNSPEC_LSETUP_END) - (clobber (match_scratch:SI 5 ""))])] + (clobber (match_operand 5 ""))])] ; match_scratch "" { /* The loop optimizer doesn't check the predicates... */ @@ -1956,6 +1957,7 @@ && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 0xFFFFFFFF) FAIL; bfin_hardware_loop (); + operands[5] = gen_rtx_SCRATCH (SImode); }) (define_insn "loop_end" diff --git a/gcc/config/c6x/c6x.md b/gcc/config/c6x/c6x.md index 99f02d5dc98..e612ef68293 100644 --- a/gcc/config/c6x/c6x.md +++ b/gcc/config/c6x/c6x.md @@ -1425,6 +1425,7 @@ ; operand 2 is the maximum number of loop iterations ; operand 3 is the number of levels of enclosed loops ; operand 4 is the label to jump to at the top of the loop +; operand 5 indicates if the loop is entered at the top (define_expand "doloop_end" [(parallel [(set (pc) (if_then_else (ne (match_operand:SI 0 "" "") @@ -1434,12 +1435,13 @@ (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) - (clobber (match_scratch:SI 5 ""))])] + (clobber (match_operand 5 ""))])] ; match_scratch "TARGET_INSNS_64PLUS && optimize" { /* The loop optimizer doesn't check the predicates... */ if (GET_MODE (operands[0]) != SImode) FAIL; + operands[5] = gen_rtx_SCRATCH (SImode); }) (define_insn "mvilc" diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index aa5e78636ea..f84f1ad6332 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -3960,7 +3960,8 @@ (use (match_operand 1 "" "")) ; iterations; zero if unknown (use (match_operand 2 "" "")) ; max iterations (use (match_operand 3 "" "")) ; loop level - (use (match_operand 4 "" ""))] ; label + (use (match_operand 4 "" "")) ; label + (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0 "" { /* Only use cloop on innermost loops. */ diff --git a/gcc/config/mep/mep.md b/gcc/config/mep/mep.md index 773a9a0aa14..35b6e1490bc 100644 --- a/gcc/config/mep/mep.md +++ b/gcc/config/mep/mep.md @@ -2079,7 +2079,8 @@ [(use (match_operand 0 "register_operand" "")) (use (match_operand:QI 1 "const_int_operand" "")) (use (match_operand:QI 2 "const_int_operand" "")) - (use (match_operand:QI 3 "const_int_operand" ""))] + (use (match_operand:QI 3 "const_int_operand" "")) + (use (match_operand 4 "" ""))] "!profile_arc_flag && TARGET_OPT_REPEAT" "if (INTVAL (operands[3]) > 1) FAIL; @@ -2115,7 +2116,8 @@ (use (match_operand:QI 1 "const_int_operand" "")) (use (match_operand:QI 2 "const_int_operand" "")) (use (match_operand:QI 3 "const_int_operand" "")) - (use (label_ref (match_operand 4 "" "")))] + (use (label_ref (match_operand 4 "" ""))) + (use (match_operand 5 "" ""))] "!profile_arc_flag && TARGET_OPT_REPEAT" "if (INTVAL (operands[3]) > 1) FAIL; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 96f4f6a8321..5bf2fec18e4 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -13085,7 +13085,8 @@ (use (match_operand 1 "" "")) ; iterations; zero if unknown (use (match_operand 2 "" "")) ; max iterations (use (match_operand 3 "" "")) ; loop level - (use (match_operand 4 "" ""))] ; label + (use (match_operand 4 "" "")) ; label + (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0 "" " { diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index efe1a470e8d..9279a9876c4 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -8166,7 +8166,8 @@ (use (match_operand 1 "" "")) ; iterations; zero if unknown (use (match_operand 2 "" "")) ; max iterations (use (match_operand 3 "" "")) ; loop level - (use (match_operand 4 "" ""))] ; label + (use (match_operand 4 "" "")) ; label + (use (match_operand 5 "" ""))] ; flag: 1 if loop entered at top, else 0 "" { if (GET_MODE (operands[0]) == SImode && !TARGET_CPU_ZARCH) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 6e6394504f6..2ef4a1a4ee0 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -8474,11 +8474,14 @@ label: (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1))) - (clobber (reg:SI T_REG))])] + (clobber (reg:SI T_REG))]) + (match_operand 5 "" "")] "TARGET_SH2" { if (GET_MODE (operands[0]) != SImode) FAIL; + emit_insn (gen_doloop_end_split (operands[0], operands[4], operands[0])); + DONE; }) (define_insn_and_split "doloop_end_split" diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md index ee5fced6665..3446e986f27 100644 --- a/gcc/config/spu/spu.md +++ b/gcc/config/spu/spu.md @@ -4490,7 +4490,8 @@ selb\t%0,%4,%0,%3" (use (match_operand 1 "" "")) ; iterations; zero if unknown (use (match_operand 2 "" "")) ; max iterations (use (match_operand 3 "" "")) ; loop level - (use (match_operand 4 "" ""))] ; label + (use (match_operand 4 "" "")) ; label + (match_operand 5 "" "")] "" " { diff --git a/gcc/config/tilegx/tilegx.md b/gcc/config/tilegx/tilegx.md index 92a6d651eda..b5dc9c8844f 100644 --- a/gcc/config/tilegx/tilegx.md +++ b/gcc/config/tilegx/tilegx.md @@ -2316,7 +2316,8 @@ (use (match_operand 1 "" "")) ;; iterations; zero if unknown (use (match_operand 2 "" "")) ;; max iterations (use (match_operand 3 "" "")) ;; loop level - (use (match_operand 4 "" ""))] ;; label + (use (match_operand 4 "" "")) ;; label + (use (match_operand 5 "" ""))] ;; flag: 1 if loop entered at top, else 0 "" { if (optimize > 0 && flag_modulo_sched) diff --git a/gcc/config/tilepro/tilepro.md b/gcc/config/tilepro/tilepro.md index 9d5d44e85ed..1d1838e6de8 100644 --- a/gcc/config/tilepro/tilepro.md +++ b/gcc/config/tilepro/tilepro.md @@ -1322,7 +1322,8 @@ (use (match_operand 1 "" "")) ;; iterations; zero if unknown (use (match_operand 2 "" "")) ;; max iterations (use (match_operand 3 "" "")) ;; loop level - (use (match_operand 4 "" ""))] ;; label + (use (match_operand 4 "" "")) ;; label + (use (match_operand 5 "" ""))] ;; flag: 1 if loop entered at top, else 0 "" { if (optimize > 0) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 6a1db6ad607..32866d5c156 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -5517,7 +5517,9 @@ iterations as a @code{const_int} or @code{const0_rtx} if this cannot be determined until run-time; operand 2 is the actual or estimated maximum number of iterations as a @code{const_int}; operand 3 is the number of enclosed loops as a @code{const_int} (an innermost loop has a value of -1); operand 4 is the label to jump to if the register is nonzero. +1); operand 4 is the label to jump to if the register is nonzero; +operand 5 is const1_rtx if the loop in entered at its top, const0_rtx +otherwise. @xref{Looping Patterns}. This optional instruction pattern should be defined for machines with diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c index 8dcfea5bba8..9be87c64aea 100644 --- a/gcc/loop-doloop.c +++ b/gcc/loop-doloop.c @@ -1,5 +1,5 @@ /* Perform doloop optimizations - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010, 2012 Free Software Foundation, Inc. Based on code by Michael P. Hayes (m.hayes@elec.canterbury.ac.nz) @@ -561,7 +561,8 @@ doloop_modify (struct loop *loop, struct niter_desc *desc, init = gen_doloop_begin (counter_reg, desc->const_iter ? desc->niter_expr : const0_rtx, iter_rtx, - GEN_INT (level)); + GEN_INT (level), + doloop_seq); if (init) { start_sequence (); @@ -619,6 +620,7 @@ doloop_optimize (struct loop *loop) unsigned word_mode_size; unsigned HOST_WIDE_INT word_mode_max; double_int iter; + int entered_at_top; if (dump_file) fprintf (dump_file, "Doloop: Processing loop %d.\n", loop->num); @@ -681,8 +683,14 @@ doloop_optimize (struct loop *loop) not like. */ start_label = block_label (desc->in_edge->dest); doloop_reg = gen_reg_rtx (mode); + entered_at_top = loop_preheader_edge (loop)->dest == desc->in_edge->dest; + fprintf (stderr, "entered at top orig: %d\n", entered_at_top); + entered_at_top = (loop->latch == desc->in_edge->dest + && contains_no_active_insn_p (loop->latch)); + fprintf (stderr, "entered at top Zdenek: %d\n", entered_at_top); doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max, - GEN_INT (level), start_label); + GEN_INT (level), start_label, + GEN_INT (entered_at_top)); word_mode_size = GET_MODE_PRECISION (word_mode); word_mode_max @@ -712,7 +720,8 @@ doloop_optimize (struct loop *loop) } PUT_MODE (doloop_reg, word_mode); doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max, - GEN_INT (level), start_label); + GEN_INT (level), start_label, + GEN_INT (entered_at_top)); } if (! doloop_seq) {