This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Rework doloop interface


On Tue, Nov 5, 2013 at 10:33 AM, Richard Sandiford
<rdsandiford@googlemail.com> wrote:
> Following on from:
>
>     http://gcc.gnu.org/ml/gcc-patches/2013-11/msg00092.html
>
> it looks like I'll have to "fix" the doloop_begin/end interface after all.
> The current code goes on to do some rtx arithmetic on invalid CONST_INTs.
> (FWIW, the arithmetic seems unnecessary and I think we could simply drop it,
> but the weirdness of the interface would remain.)
>
> So: doloop_end has 6 parameters, of which 4 are really just information
> about the loop.  These 4 parameters never end up in the instruction
> stream on current targets and aren't IMO really rtxes.  But because
> expanders can only take rtx arguments, we still need to wrap them in
> some kind of rtx container.
>
> This causes problems because once you start representing something as
> an rtx, you need to start thinking about modes.  One of the parameters
> is the maximum number of iterations, and it isn't obvious what its mode
> should be; the mode of the loop counter is too small to hold an iteration
> count of 1 << GET_MODE_PRECISION.  Another of the parameters is the loop
> level, which has no obvious mode at all.  One is a boolean, which could
> be represented as BImode, but then we enter STORE_FLAG_VALUE territory.
>
> So this patch adds a new target hook, can_use_doloop_p, that takes
> these parameters as normal C arguments.  The default returns true,
> but there's also a canned alternative for targets that can only handle
> innermost loops.
>
> This should also be slightly more efficient, since we can avoid creating
> the loop counter register and label if the loop "obviously" isn't suitable.
> It also avoids creating garbage rtl for the 4 not-really-rtx parameters.
>
> Tested by building C and C++ for:
>
>         arc-elf
>         arm-linux-gnueabi
>         bfin-elf
>         c6x-elf
>         ia64-linux-gnu
>         mep-elf
>         powerpc-linux-gnu
>         s390-linux-gnu
>         sh-linux-gnu
>         spu-elf
>         tilegx-elf
>         tilepro-elf
>         v850-elf
>
> and comparing the -O2 assembly output of gcc.c-torture, gcc.dg and g++.dg
> from before and after the patch (as far as possible without target headers).
> For this I moved the can_use_doloop_p test to just before the gen_doloop_end
> so that register and label numbers stayed the same.  There were two
> differences:
>
> - gcc.c-torture/compile/pr44030.c for arc-elf, where we now use the doloop
>   instruction and didn't previously.  This is because arc-elf checked:
>
>     /* Setting up the loop with two sr isntructions costs 6 cycles.  */
>     if (TARGET_ARC700 && !INTVAL (operands[5])
>         && INTVAL (operands[1]) && INTVAL (operands[1]) <= (flag_pic ? 6 : 3))
>       FAIL;
>
>   where operands[1] is the constant number of iterations.  Unlike the
>   maximum number of iterations (operands[2]), this value has the same
>   mode as the counter register and is properly sign-extended.  So a large
>   positive iteration count appears negative and unintentionally triggered
>   the FAIL.  So I think this counts as a bug fix.
>
> - gcc.dg/graphite/id-9.c for bfin-elf.  In this testcase the maximum number
>   of iterations is calculated as the double_int { high = 0, low = -1 },
>   which doesn't fit in a signed HWI, so the maximum number of iterations
>   was previously treated as 0.  And the bfin code doesn't handle the
>   0/unknown case, which might be a bug:
>
>     /* Due to limitations in the hardware (an initial loop count of 0
>        does not loop 2^32 times) we must avoid to generate a hardware
>        loops when we cannot rule out this case.  */
>     if (!flag_unsafe_loop_optimizations
>         && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 0xFFFFFFFF)
>       FAIL;
>
>   So the old code allowed the doloop to be used here, which I don't
>   think was intentional.  Now the bfin code sees the original double_int
>   and rejects it as too big.
>
>   That said, it might also be a bug that we have { 0, -1 } rather than
>   { 0, 0xffffffff } or { 0, 0x100000000 } (or even { -1, -1 }) for an
>   SImode loop, but this has got to stop somewhere...
>
> Also bootstrapped & regression-tested on powerpc64-linux-gnu.  OK to install?

Ok.  Please leave target maintainers a second to comment.

Thanks,
Richard.

> Thanks,
> Richard
>
>
> gcc/
>         * target.def (can_use_doloop_p): New hook.
>         * doc/tm.texi.in (TARGET_CAN_USE_DOLOOP_P): Add.
>         * doc/tm.texi: Regenerate.
>         * doc/md.texi (doloop_begin, doloop_end): Update documentation.
>         * hooks.h (hook_bool_dint_dint_uint_true): Declare.
>         * hooks.c (hook_bool_dint_dint_uint_true): New function.
>         * targhooks.h (can_use_doloop_if_innermost): Declare.
>         * targhooks.c (can_use_doloop_if_innermost): New function.
>         * target.h: Include double-int.h.
>         * loop-doloop.c (doloop_optimize): Call targetm.can_use_doloop_p.
>         Remove iteration count, maximum iteration count, loop depth and
>         enter-at-top inputs from doloop_begin and doloop_end.
>         * config/arc/arc.md (doloop_begin, doloop_end): Update for new
>         interface.
>         * config/arc/arc.c (arc_can_use_doloop_p): New function.
>         (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/arm/thumb2.md (doloop_end): Update for new interface.
>         * config/arm/arm.c (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/bfin/bfin.md (doloop_end): Update for new interface.
>         * config/bfin/bfin.c (bfin_can_use_doloop_p): New function.
>         (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/c6x/c6x.md (doloop_end): Update for new interface.
>         * config/ia64/ia64.md (doloop_end): Update for new interface.
>         * config/ia64/ia64.c (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/mep/mep.md (doloop_begin, doloop_end): Update for new
>         interface.
>         * config/mep/mep.c (mep_emit_doloop): Likewise.
>         (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/rs6000/rs6000.md (doloop_end): Update for new interface.
>         * config/rs6000/rs6000.c (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/s390/s390.md (doloop_end): Update for new interface.
>         * config/sh/sh.md (doloop_end): Likewise.
>         * config/spu/spu.md (doloop_end): Likewise.
>         * config/spu/spu.c (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/tilegx/tilegx.md (doloop_end): Update for new interface.
>         * config/tilegx/tilegx.c (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/tilepro/tilepro.md (doloop_end): Update for new interface.
>         * config/tilepro/tilepro.c (TARGET_CAN_USE_DOLOOP_P): Define.
>         * config/v850/v850.md (doloop_begin, doloop_end): Update for new
>         interface.
>         * config/v850/v850.c (TARGET_CAN_USE_DOLOOP_P): Define.
>
> Index: gcc/target.def
> ===================================================================
> --- gcc/target.def      2013-11-05 08:55:57.423644646 +0000
> +++ gcc/target.def      2013-11-05 08:56:11.617792832 +0000
> @@ -3572,6 +3572,23 @@ normally defined in @file{libgcc2.c}.",
>   tree, (void),
>   default_external_stack_protect_fail)
>
> +DEFHOOK
> +(can_use_doloop_p,
> + "Return true if it is possible to use low-overhead loops (@code{doloop_end}\n\
> +and @code{doloop_begin}) for a particular loop.  @var{iterations} gives the\n\
> +exact number of iterations, or 0 if not known.  @var{iterations_max} gives\n\
> +the maximum number of iterations, or 0 if not known.  @var{loop_depth} is\n\
> +the nesting depth of the loop, with 1 for innermost loops, 2 for loops that\n\
> +contain innermost loops, and so on.  @var{entered_at_top} is true if the\n\
> +loop is only entered from the top.\n\
> +\n\
> +This hook is only used if @code{doloop_end} is available.  The default\n\
> +implementation returns true.  You can use @code{can_use_doloop_if_innermost}\n\
> +if the loop must be the innermost, and if there are no other restrictions.",
> + bool, (double_int iterations, double_int iterations_max,
> +       unsigned int loop_depth, bool entered_at_top),
> + hook_bool_dint_dint_uint_bool_true)
> +
>  /* Returns NULL if target supports the insn within a doloop block,
>     otherwise it returns an error message.  */
>  DEFHOOK
> Index: gcc/doc/tm.texi.in
> ===================================================================
> --- gcc/doc/tm.texi.in  2013-11-05 08:55:57.423644646 +0000
> +++ gcc/doc/tm.texi.in  2013-11-05 08:56:11.616792820 +0000
> @@ -8206,6 +8206,8 @@ to by @var{ce_info}.
>
>  @hook TARGET_GENERATE_VERSION_DISPATCHER_BODY
>
> +@hook TARGET_CAN_USE_DOLOOP_P
> +
>  @hook TARGET_INVALID_WITHIN_DOLOOP
>
>  @hook TARGET_LEGITIMATE_COMBINED_INSN
> Index: gcc/doc/tm.texi
> ===================================================================
> --- gcc/doc/tm.texi     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/doc/tm.texi     2013-11-05 08:56:11.614792799 +0000
> @@ -11076,6 +11076,20 @@ function version at run-time for a given
>  body must be generated.
>  @end deftypefn
>
> +@deftypefn {Target Hook} bool TARGET_CAN_USE_DOLOOP_P (double_int @var{iterations}, double_int @var{iterations_max}, unsigned int @var{loop_depth}, bool @var{entered_at_top})
> +Return true if it is possible to use low-overhead loops (@code{doloop_end}
> +and @code{doloop_begin}) for a particular loop.  @var{iterations} gives the
> +exact number of iterations, or 0 if not known.  @var{iterations_max} gives
> +the maximum number of iterations, or 0 if not known.  @var{loop_depth} is
> +the nesting depth of the loop, with 1 for innermost loops, 2 for loops that
> +contain innermost loops, and so on.  @var{entered_at_top} is true if the
> +loop is only entered from the top.
> +
> +This hook is only used if @code{doloop_end} is available.  The default
> +implementation returns true.  You can use @code{can_use_doloop_if_innermost}
> +if the loop must be the innermost, and if there are no other restrictions.
> +@end deftypefn
> +
>  @deftypefn {Target Hook} {const char *} TARGET_INVALID_WITHIN_DOLOOP (const_rtx @var{insn})
>
>  Take an instruction in @var{insn} and return NULL if it is valid within a
> Index: gcc/doc/md.texi
> ===================================================================
> --- gcc/doc/md.texi     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/doc/md.texi     2013-11-05 08:56:11.612792780 +0000
> @@ -5856,34 +5856,27 @@ reduction is enabled.
>
>  @cindex @code{doloop_end} instruction pattern
>  @item @samp{doloop_end}
> -Conditional branch instruction that decrements a register and jumps if
> -the register is nonzero.  This instruction takes five operands: Operand
> -0 is the register to decrement and test; operand 1 is the number of loop
> -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;
> -operand 5 is const1_rtx if the loop in entered at its top, const0_rtx
> -otherwise.
> +Conditional branch instruction that decrements a register and
> +jumps if the register is nonzero.  Operand 0 is the register to
> +decrement and test; operand 1 is the label to jump to if the
> +register is nonzero.
>  @xref{Looping Patterns}.
>
>  This optional instruction pattern should be defined for machines with
>  low-overhead looping instructions as the loop optimizer will try to
> -modify suitable loops to utilize it.  If nested low-overhead looping is
> -not supported, use a @code{define_expand} (@pxref{Expander Definitions})
> -and make the pattern fail if operand 3 is not @code{const1_rtx}.
> -Similarly, if the actual or estimated maximum number of iterations is
> -too large for this instruction, make it fail.
> +modify suitable loops to utilize it.  The target hook
> +@code{TARGET_CAN_USE_DOLOOP_P} controls the conditions under which
> +low-overhead loops can be used.
>
>  @cindex @code{doloop_begin} instruction pattern
>  @item @samp{doloop_begin}
>  Companion instruction to @code{doloop_end} required for machines that
> -need to perform some initialization, such as loading special registers
> -used by a low-overhead looping instruction.  If initialization insns do
> -not always need to be emitted, use a @code{define_expand}
> -(@pxref{Expander Definitions}) and make it fail.
> +need to perform some initialization, such as loading a special counter
> +register.  Operand 1 is the associated @code{doloop_end} pattern and
> +operand 0 is the register that it decrements.
>
> +If initialization insns do not always need to be emitted, use a
> +@code{define_expand} (@pxref{Expander Definitions}) and make it fail.
>
>  @cindex @code{canonicalize_funcptr_for_compare} instruction pattern
>  @item @samp{canonicalize_funcptr_for_compare}
> Index: gcc/hooks.h
> ===================================================================
> --- gcc/hooks.h 2013-11-05 08:55:57.423644646 +0000
> +++ gcc/hooks.h 2013-11-05 08:56:11.616792820 +0000
> @@ -23,6 +23,7 @@
>  #define GCC_HOOKS_H
>
>  #include "machmode.h"
> +#include "double-int.h"
>
>  extern bool hook_bool_void_false (void);
>  extern bool hook_bool_void_true (void);
> @@ -60,6 +61,8 @@ extern bool hook_bool_rtx_int_int_int_in
>  extern bool hook_bool_tree_tree_false (tree, tree);
>  extern bool hook_bool_tree_tree_true (tree, tree);
>  extern bool hook_bool_tree_bool_false (tree, bool);
> +extern bool hook_bool_dint_dint_uint_bool_true (double_int, double_int,
> +                                               unsigned int, bool);
>
>  extern void hook_void_void (void);
>  extern void hook_void_constcharptr (const char *);
> Index: gcc/hooks.c
> ===================================================================
> --- gcc/hooks.c 2013-11-05 08:55:57.423644646 +0000
> +++ gcc/hooks.c 2013-11-05 08:56:11.616792820 +0000
> @@ -331,6 +331,12 @@ hook_bool_rtx_int_int_int_intp_bool_fals
>    return false;
>  }
>
> +bool
> +hook_bool_dint_dint_uint_bool_true (double_int, double_int, unsigned int, bool)
> +{
> +  return true;
> +}
> +
>  /* Generic hook that takes an rtx and returns it.  */
>  rtx
>  hook_rtx_rtx_identity (rtx x)
> Index: gcc/targhooks.h
> ===================================================================
> --- gcc/targhooks.h     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/targhooks.h     2013-11-05 08:56:11.618792842 +0000
> @@ -211,3 +211,5 @@ extern tree default_fn_abi_va_list_bound
>  extern tree default_chkp_bound_type (void);
>  extern enum machine_mode default_chkp_bound_mode (void);
>  extern tree default_builtin_chkp_function (unsigned int);
> +extern bool can_use_doloop_if_innermost (double_int, double_int,
> +                                        unsigned int, bool);
> Index: gcc/targhooks.c
> ===================================================================
> --- gcc/targhooks.c     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/targhooks.c     2013-11-05 08:56:11.618792842 +0000
> @@ -1718,5 +1718,14 @@ default_builtin_chkp_function (unsigned
>    return NULL_TREE;
>  }
>
> +/* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do
> +   not support nested low-overhead loops.  */
> +
> +bool
> +can_use_doloop_if_innermost (double_int, double_int,
> +                            unsigned int loop_depth, bool)
> +{
> +  return loop_depth == 1;
> +}
>
>  #include "gt-targhooks.h"
> Index: gcc/target.h
> ===================================================================
> --- gcc/target.h        2013-11-05 08:55:57.423644646 +0000
> +++ gcc/target.h        2013-11-05 08:56:11.618792842 +0000
> @@ -50,6 +50,7 @@ #define GCC_TARGET_H
>
>  #include "insn-modes.h"
>  #include "insn-codes.h"
> +#include "double-int.h"
>
>  #ifdef ENABLE_CHECKING
>
> Index: gcc/loop-doloop.c
> ===================================================================
> --- gcc/loop-doloop.c   2013-11-05 08:55:57.422644636 +0000
> +++ gcc/loop-doloop.c   2013-11-05 08:56:11.616792820 +0000
> @@ -548,20 +548,8 @@ doloop_modify (struct loop *loop, struct
>  #ifdef HAVE_doloop_begin
>    {
>      rtx init;
> -    unsigned level = get_loop_level (loop) + 1;
> -    double_int iter;
> -    rtx iter_rtx;
> -
> -    if (!get_max_loop_iterations (loop, &iter)
> -       || !iter.fits_shwi ())
> -      iter_rtx = const0_rtx;
> -    else
> -      iter_rtx = GEN_INT (iter.to_shwi ());
> -    init = gen_doloop_begin (counter_reg,
> -                            desc->const_iter ? desc->niter_expr : const0_rtx,
> -                            iter_rtx,
> -                            GEN_INT (level),
> -                            doloop_seq);
> +
> +    init = gen_doloop_begin (counter_reg, doloop_seq);
>      if (init)
>        {
>         start_sequence ();
> @@ -608,8 +596,8 @@ doloop_optimize (struct loop *loop)
>  {
>    enum machine_mode mode;
>    rtx doloop_seq, doloop_pat, doloop_reg;
> -  rtx iterations, count;
> -  rtx iterations_max;
> +  rtx count;
> +  double_int iterations, iterations_max;
>    rtx start_label;
>    rtx condition;
>    unsigned level, est_niter;
> @@ -617,7 +605,6 @@ doloop_optimize (struct loop *loop)
>    struct niter_desc *desc;
>    unsigned word_mode_size;
>    unsigned HOST_WIDE_INT word_mode_max;
> -  double_int iter;
>    int entered_at_top;
>
>    if (dump_file)
> @@ -667,25 +654,30 @@ doloop_optimize (struct loop *loop)
>        return false;
>      }
>
> -  count = copy_rtx (desc->niter_expr);
> -  iterations = desc->const_iter ? desc->niter_expr : const0_rtx;
> -  if (!get_max_loop_iterations (loop, &iter)
> -      || !iter.fits_shwi ())
> -    iterations_max = const0_rtx;
> +  if (desc->const_iter)
> +    iterations = rtx_to_double_int (desc->niter_expr);
>    else
> -    iterations_max = GEN_INT (iter.to_shwi ());
> +    iterations = double_int_zero;
> +  if (!get_max_loop_iterations (loop, &iterations_max))
> +    iterations_max = double_int_zero;
>    level = get_loop_level (loop) + 1;
> +  entered_at_top = (loop->latch == desc->in_edge->dest
> +                   && contains_no_active_insn_p (loop->latch));
> +  if (!targetm.can_use_doloop_p (iterations, iterations_max, level,
> +                                entered_at_top))
> +    {
> +      if (dump_file)
> +       fprintf (dump_file, "Loop rejected by can_use_doloop_p.\n");
> +      return false;
> +    }
>
>    /* Generate looping insn.  If the pattern FAILs then give up trying
>       to modify the loop since there is some aspect the back-end does
>       not like.  */
> +  count = copy_rtx (desc->niter_expr);
>    start_label = block_label (desc->in_edge->dest);
>    doloop_reg = gen_reg_rtx (mode);
> -  entered_at_top = (loop->latch == desc->in_edge->dest
> -                   && contains_no_active_insn_p (loop->latch));
> -  doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
> -                              GEN_INT (level), start_label,
> -                              GEN_INT (entered_at_top));
> +  doloop_seq = gen_doloop_end (doloop_reg, start_label);
>
>    word_mode_size = GET_MODE_PRECISION (word_mode);
>    word_mode_max
> @@ -696,27 +688,14 @@ doloop_optimize (struct loop *loop)
>          computed, we must be sure that the number of iterations fits into
>          the new mode.  */
>        && (word_mode_size >= GET_MODE_PRECISION (mode)
> -         || iter.ule (double_int::from_shwi (word_mode_max))))
> +         || iterations_max.ule (double_int::from_shwi (word_mode_max))))
>      {
>        if (word_mode_size > GET_MODE_PRECISION (mode))
> -       {
> -         count = simplify_gen_unary (ZERO_EXTEND, word_mode,
> -                                     count, mode);
> -         iterations = simplify_gen_unary (ZERO_EXTEND, word_mode,
> -                                          iterations, mode);
> -         iterations_max = simplify_gen_unary (ZERO_EXTEND, word_mode,
> -                                              iterations_max, mode);
> -       }
> +       count = simplify_gen_unary (ZERO_EXTEND, word_mode, count, mode);
>        else
> -       {
> -         count = lowpart_subreg (word_mode, count, mode);
> -         iterations = lowpart_subreg (word_mode, iterations, mode);
> -         iterations_max = lowpart_subreg (word_mode, iterations_max, mode);
> -       }
> +       count = lowpart_subreg (word_mode, count, mode);
>        PUT_MODE (doloop_reg, word_mode);
> -      doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
> -                                  GEN_INT (level), start_label,
> -                                  GEN_INT (entered_at_top));
> +      doloop_seq = gen_doloop_end (doloop_reg, start_label);
>      }
>    if (! doloop_seq)
>      {
> Index: gcc/config/arc/arc.md
> ===================================================================
> --- gcc/config/arc/arc.md       2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/arc/arc.md       2013-11-05 08:56:11.069787126 +0000
> @@ -4706,16 +4706,10 @@ (define_insn_and_split "*bbit_di"
>  })
>
>  ; operand 0 is the loop count pseudo register
> -; operand 1 is the number of loop iterations or 0 if it is unknown
> -; operand 2 is the maximum number of loop iterations
> -; operand 3 is the number of levels of enclosed loops
> -; operand 4 is the loop end pattern
> +; operand 1 is the loop end pattern
>  (define_expand "doloop_begin"
>    [(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 4 "" ""))]
> +   (use (match_operand 1 "" ""))]
>    ""
>  {
>    /* Using the INSN_UID of the loop end pattern to identify it causes
> @@ -4725,10 +4719,8 @@ (define_expand "doloop_begin"
>       still be able to tell what kind of number this is.  */
>    static HOST_WIDE_INT loop_end_id = 0;
>
> -  if (INTVAL (operands[3]) > 1)
> -    FAIL;
>    rtx id = GEN_INT (--loop_end_id);
> -  XEXP (XVECEXP (PATTERN (operands[4]), 0, 4), 0) = id;
> +  XEXP (XVECEXP (PATTERN (operands[1]), 0, 4), 0) = id;
>    emit_insn (gen_doloop_begin_i (operands[0], const0_rtx, id,
>                                  const0_rtx, const0_rtx));
>    DONE;
> @@ -4907,11 +4899,7 @@ (define_insn "doloop_begin_i"
>  )
>
>  ; operand 0 is the loop count pseudo register
> -; operand 1 is the number of loop iterations or 0 if it is unknown
> -; 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 is nonzero if the loop is entered at its top.
> +; operand 1 is the label to jump to at the top of the loop
>  ; Use this for the ARC600 and ARC700.  For ARCtangent-A5, this is unsafe
>  ; without further checking for nearby branches etc., and without proper
>  ; annotation of shift patterns that clobber lp_count
> @@ -4919,24 +4907,14 @@ (define_insn "doloop_begin_i"
>  ; single insn - loop setup is expensive then.
>  (define_expand "doloop_end"
>    [(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 (label_ref (match_operand 4 "" "")))
> -   (use (match_operand:QI 5 "const_int_operand" ""))]
> +   (use (label_ref (match_operand 1 "" "")))]
>    "TARGET_ARC600 || TARGET_ARC700"
>  {
> -  if (INTVAL (operands[3]) > 1)
> -    FAIL;
> -  /* Setting up the loop with two sr isntructions costs 6 cycles.  */
> -  if (TARGET_ARC700 && !INTVAL (operands[5])
> -      && INTVAL (operands[1]) && INTVAL (operands[1]) <= (flag_pic ? 6 : 3))
> -    FAIL;
>    /* We could do smaller bivs with biv widening, and wider bivs by having
>       a high-word counter in an outer loop - but punt on this for now.  */
>    if (GET_MODE (operands[0]) != SImode)
>      FAIL;
> -  emit_jump_insn (gen_doloop_end_i (operands[0], operands[4], const0_rtx));
> +  emit_jump_insn (gen_doloop_end_i (operands[0], operands[1], const0_rtx));
>    DONE;
>  })
>
> Index: gcc/config/arc/arc.c
> ===================================================================
> --- gcc/config/arc/arc.c        2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/arc/arc.c        2013-11-05 08:56:11.045786876 +0000
> @@ -388,6 +388,7 @@ static bool arc_return_in_memory (const_
>  static void arc_init_simd_builtins (void);
>  static bool arc_vector_mode_supported_p (enum machine_mode);
>
> +static bool arc_can_use_doloop_p (double_int, double_int, unsigned int, bool);
>  static const char *arc_invalid_within_doloop (const_rtx);
>
>  static void output_short_suffix (FILE *file);
> @@ -493,6 +494,9 @@ #define TARGET_SCHED_ADJUST_PRIORITY arc
>  #undef TARGET_VECTOR_MODE_SUPPORTED_P
>  #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
>
> +#undef TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
> +
>  #undef TARGET_INVALID_WITHIN_DOLOOP
>  #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
>
> @@ -5638,6 +5642,23 @@ arc_pass_by_reference (cumulative_args_t
>               || TREE_ADDRESSABLE (type)));
>  }
>
> +/* Implement TARGET_CAN_USE_DOLOOP_P.  */
> +
> +static bool
> +arc_can_use_doloop_p (double_int iterations, double_int,
> +                     unsigned int loop_depth, bool entered_at_top)
> +{
> +  if (loop_depth > 1)
> +    return false;
> +  /* Setting up the loop with two sr instructions costs 6 cycles.  */
> +  if (TARGET_ARC700
> +      && !entered_at_top
> +      && iterations.high == 0
> +      && iterations.low > 0
> +      && iterations.low <= (flag_pic ? 6 : 3))
> +    return false;
> +  return true;
> +}
>
>  /* NULL if INSN insn is valid within a low-overhead loop.
>     Otherwise return why doloop cannot be applied.  */
> Index: gcc/config/arm/thumb2.md
> ===================================================================
> --- gcc/config/arm/thumb2.md    2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/arm/thumb2.md    2013-11-05 08:56:11.212788615 +0000
> @@ -1449,11 +1449,7 @@ (define_peephole2
>  ;; knows what to generate.
>  (define_expand "doloop_end"
>    [(use (match_operand 0 "" ""))      ; loop pseudo
> -   (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 5 "" ""))]     ; flag: 1 if loop entered at top, else 0
> +   (use (match_operand 1 "" ""))]     ; label
>    "TARGET_32BIT"
>    "
>   {
> @@ -1472,10 +1468,6 @@ (define_expand "doloop_end"
>       rtx insn;
>       rtx cmp;
>
> -     /* Only use this on innermost loops.  */
> -     if (INTVAL (operands[3]) > 1)
> -       FAIL;
> -
>       if (GET_MODE (operands[0]) != SImode)
>         FAIL;
>
> @@ -1488,7 +1480,7 @@ (define_expand "doloop_end"
>       cmp = XVECEXP (PATTERN (insn), 0, 0);
>       cc_reg = SET_DEST (cmp);
>       bcomp = gen_rtx_NE (VOIDmode, cc_reg, const0_rtx);
> -     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
> +     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
>       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
>                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
>                                                          loc_ref, pc_rtx)));
> Index: gcc/config/arm/arm.c
> ===================================================================
> --- gcc/config/arm/arm.c        2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/arm/arm.c        2013-11-05 08:56:11.211788604 +0000
> @@ -669,6 +669,8 @@ #define TARGET_ASAN_SHADOW_OFFSET arm_as
>  #undef MAX_INSN_PER_IT_BLOCK
>  #define MAX_INSN_PER_IT_BLOCK (arm_restrict_it ? 1 : 4)
>
> +#undef TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
>
>  struct gcc_target targetm = TARGET_INITIALIZER;
>
> Index: gcc/config/bfin/bfin.md
> ===================================================================
> --- gcc/config/bfin/bfin.md     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/bfin/bfin.md     2013-11-05 08:56:11.619792853 +0000
> @@ -1929,35 +1929,25 @@ (define_insn "*tablejump_internal"
>  ;;  Hardware loop
>
>  ; operand 0 is the loop count pseudo register
> -; operand 1 is the number of loop iterations or 0 if it is unknown
> -; 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
> +; operand 1 is the label to jump to at the top of the loop
>  (define_expand "doloop_end"
>    [(parallel [(set (pc) (if_then_else
>                           (ne (match_operand:SI 0 "" "")
>                               (const_int 1))
> -                         (label_ref (match_operand 4 "" ""))
> +                         (label_ref (match_operand 1 "" ""))
>                           (pc)))
>               (set (match_dup 0)
>                    (plus:SI (match_dup 0)
>                             (const_int -1)))
>               (unspec [(const_int 0)] UNSPEC_LSETUP_END)
> -             (clobber (match_operand 5 ""))])] ; match_scratch
> +             (clobber (match_dup 2))])] ; match_scratch
>    ""
>  {
>    /* The loop optimizer doesn't check the predicates... */
>    if (GET_MODE (operands[0]) != SImode)
>      FAIL;
> -  /* Due to limitations in the hardware (an initial loop count of 0
> -     does not loop 2^32 times) we must avoid to generate a hardware
> -     loops when we cannot rule out this case.  */
> -  if (!flag_unsafe_loop_optimizations
> -      && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 0xFFFFFFFF)
> -    FAIL;
>    bfin_hardware_loop ();
> -  operands[5] = gen_rtx_SCRATCH (SImode);
> +  operands[2] = gen_rtx_SCRATCH (SImode);
>  })
>
>  (define_insn "loop_end"
> Index: gcc/config/bfin/bfin.c
> ===================================================================
> --- gcc/config/bfin/bfin.c      2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/bfin/bfin.c      2013-11-05 08:56:11.367790231 +0000
> @@ -3366,6 +3366,22 @@ find_prev_insn_start (rtx insn)
>    return insn;
>  }
>
> +/* Implement TARGET_CAN_USE_DOLOOP_P.  */
> +
> +static bool
> +bfin_can_use_doloop_p (double_int, double_int iterations_max,
> +                      unsigned int, bool)
> +{
> +  /* Due to limitations in the hardware (an initial loop count of 0
> +     does not loop 2^32 times) we must avoid to generate a hardware
> +     loops when we cannot rule out this case.  */
> +  if (!flag_unsafe_loop_optimizations
> +      && (iterations_max.high != 0
> +         || iterations_max.low >= 0xFFFFFFFF))
> +    return false;
> +  return true;
> +}
> +
>  /* Increment the counter for the number of loop instructions in the
>     current function.  */
>
> @@ -5810,4 +5826,7 @@ #define TARGET_DELAY_SCHED2 true
>  #undef TARGET_DELAY_VARTRACK
>  #define TARGET_DELAY_VARTRACK true
>
> +#undef TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
> +
>  struct gcc_target targetm = TARGET_INITIALIZER;
> Index: gcc/config/c6x/c6x.md
> ===================================================================
> --- gcc/config/c6x/c6x.md       2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/c6x/c6x.md       2013-11-05 08:56:11.384790405 +0000
> @@ -1421,27 +1421,23 @@ (define_insn_and_split "eh_return"
>  ;; -------------------------------------------------------------------------
>
>  ; operand 0 is the loop count pseudo register
> -; operand 1 is the number of loop iterations or 0 if it is unknown
> -; 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
> +; operand 1 is the label to jump to at the top of the loop
>  (define_expand "doloop_end"
>    [(parallel [(set (pc) (if_then_else
>                           (ne (match_operand:SI 0 "" "")
>                               (const_int 1))
> -                         (label_ref (match_operand 4 "" ""))
> +                         (label_ref (match_operand 1 "" ""))
>                           (pc)))
>               (set (match_dup 0)
>                    (plus:SI (match_dup 0)
>                             (const_int -1)))
> -             (clobber (match_operand 5 ""))])] ; match_scratch
> +             (clobber (match_dup 2))])] ; 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);
> +  operands[2] = gen_rtx_SCRATCH (SImode);
>  })
>
>  (define_insn "mvilc"
> Index: gcc/config/ia64/ia64.md
> ===================================================================
> --- gcc/config/ia64/ia64.md     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/ia64/ia64.md     2013-11-05 08:56:11.389790457 +0000
> @@ -3956,18 +3956,11 @@ (define_insn "*br_false"
>
>  (define_expand "doloop_end"
>    [(use (match_operand 0 "" ""))       ; loop pseudo
> -   (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 5 "" ""))]      ; flag: 1 if loop entered at top, else 0
> +   (use (match_operand 1 "" ""))]      ; label
>    ""
>  {
> -  /* Only use cloop on innermost loops.  */
> -  if (INTVAL (operands[3]) > 1)
> -    FAIL;
>    emit_jump_insn (gen_doloop_end_internal (gen_rtx_REG (DImode, AR_LC_REGNUM),
> -                                          operands[4]));
> +                                          operands[1]));
>    DONE;
>  })
>
> Index: gcc/config/ia64/ia64.c
> ===================================================================
> --- gcc/config/ia64/ia64.c      2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/ia64/ia64.c      2013-11-05 08:56:11.387790438 +0000
> @@ -620,6 +620,8 @@ #define TARGET_CAN_ELIMINATE ia64_can_el
>  #undef TARGET_TRAMPOLINE_INIT
>  #define TARGET_TRAMPOLINE_INIT ia64_trampoline_init
>
> +#undef TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
>  #undef TARGET_INVALID_WITHIN_DOLOOP
>  #define TARGET_INVALID_WITHIN_DOLOOP hook_constcharptr_const_rtx_null
>
> Index: gcc/config/mep/mep.md
> ===================================================================
> --- gcc/config/mep/mep.md       2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/mep/mep.md       2013-11-05 08:56:11.391790478 +0000
> @@ -2076,14 +2076,9 @@ (define_insn "doloop_begin_internal"
>
>  (define_expand "doloop_begin"
>    [(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 4 "" ""))]
> +   (use (match_operand 1 "" ""))]
>    "!profile_arc_flag && TARGET_OPT_REPEAT"
> -  "if (INTVAL (operands[3]) > 1)
> -     FAIL;
> -   mep_emit_doloop (operands, 0);
> +  "mep_emit_doloop (operands, 0);
>     DONE;
>    ")
>
> @@ -2112,15 +2107,9 @@ (define_insn "doloop_end_internal"
>
>  (define_expand "doloop_end"
>    [(use (match_operand 0 "nonimmediate_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 (label_ref (match_operand 4 "" "")))
> -   (use (match_operand 5 "" ""))]
> +   (use (label_ref (match_operand 1 "" "")))]
>    "!profile_arc_flag && TARGET_OPT_REPEAT"
> -  "if (INTVAL (operands[3]) > 1)
> -     FAIL;
> -   if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) != SImode)
> +  "if (GET_CODE (operands[0]) == REG && GET_MODE (operands[0]) != SImode)
>       FAIL;
>     mep_emit_doloop (operands, 1);
>     DONE;
> Index: gcc/config/mep/mep.c
> ===================================================================
> --- gcc/config/mep/mep.c        2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/mep/mep.c        2013-11-05 08:56:11.390790467 +0000
> @@ -5103,7 +5103,7 @@ mep_emit_doloop (rtx *operands, int is_e
>
>    tag = GEN_INT (cfun->machine->doloop_tags - 1);
>    if (is_end)
> -    emit_jump_insn (gen_doloop_end_internal (operands[0], operands[4], tag));
> +    emit_jump_insn (gen_doloop_end_internal (operands[0], operands[1], tag));
>    else
>      emit_insn (gen_doloop_begin_internal (operands[0], operands[0], tag));
>  }
> @@ -7280,6 +7280,8 @@ #define TARGET_CONDITIONAL_REGISTER_USAG
>  #define TARGET_TRAMPOLINE_INIT         mep_trampoline_init
>  #undef  TARGET_LEGITIMATE_CONSTANT_P
>  #define TARGET_LEGITIMATE_CONSTANT_P   mep_legitimate_constant_p
> +#undef  TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P                can_use_doloop_if_innermost
>
>  struct gcc_target targetm = TARGET_INITIALIZER;
>
> Index: gcc/config/rs6000/rs6000.md
> ===================================================================
> --- gcc/config/rs6000/rs6000.md 2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/rs6000/rs6000.md 2013-11-05 08:56:11.430790883 +0000
> @@ -14791,28 +14791,21 @@ (define_insn "group_ending_nop"
>
>  (define_expand "doloop_end"
>    [(use (match_operand 0 "" ""))       ; loop pseudo
> -   (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 5 "" ""))]      ; flag: 1 if loop entered at top, else 0
> +   (use (match_operand 1 "" ""))]      ; label
>    ""
>    "
>  {
> -  /* Only use this on innermost loops.  */
> -  if (INTVAL (operands[3]) > 1)
> -    FAIL;
>    if (TARGET_64BIT)
>      {
>        if (GET_MODE (operands[0]) != DImode)
>         FAIL;
> -      emit_jump_insn (gen_ctrdi (operands[0], operands[4]));
> +      emit_jump_insn (gen_ctrdi (operands[0], operands[1]));
>      }
>    else
>      {
>        if (GET_MODE (operands[0]) != SImode)
>         FAIL;
> -      emit_jump_insn (gen_ctrsi (operands[0], operands[4]));
> +      emit_jump_insn (gen_ctrsi (operands[0], operands[1]));
>      }
>    DONE;
>  }")
> Index: gcc/config/rs6000/rs6000.c
> ===================================================================
> --- gcc/config/rs6000/rs6000.c  2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/rs6000/rs6000.c  2013-11-05 08:56:11.397790540 +0000
> @@ -1593,6 +1593,9 @@ #define TARGET_LEGITIMATE_CONSTANT_P rs6
>
>  #undef TARGET_VECTORIZE_VEC_PERM_CONST_OK
>  #define TARGET_VECTORIZE_VEC_PERM_CONST_OK rs6000_vectorize_vec_perm_const_ok
> +
> +#undef TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
>
>
>  /* Processor table.  */
> Index: gcc/config/s390/s390.md
> ===================================================================
> --- gcc/config/s390/s390.md     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/s390/s390.md     2013-11-05 08:56:11.551792144 +0000
> @@ -8412,19 +8412,15 @@ (define_insn_and_split "*brx_31bit"
>
>  (define_expand "doloop_end"
>    [(use (match_operand 0 "" ""))        ; loop pseudo
> -   (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 5 "" ""))]       ; flag: 1 if loop entered at top, else 0
> +   (use (match_operand 1 "" ""))]       ; label
>    ""
>  {
>    if (GET_MODE (operands[0]) == SImode && !TARGET_CPU_ZARCH)
> -    emit_jump_insn (gen_doloop_si31 (operands[4], operands[0], operands[0]));
> +    emit_jump_insn (gen_doloop_si31 (operands[1], operands[0], operands[0]));
>    else if (GET_MODE (operands[0]) == SImode && TARGET_CPU_ZARCH)
> -    emit_jump_insn (gen_doloop_si64 (operands[4], operands[0], operands[0]));
> +    emit_jump_insn (gen_doloop_si64 (operands[1], operands[0], operands[0]));
>    else if (GET_MODE (operands[0]) == DImode && TARGET_ZARCH)
> -    emit_jump_insn (gen_doloop_di (operands[4], operands[0], operands[0]));
> +    emit_jump_insn (gen_doloop_di (operands[1], operands[0], operands[0]));
>    else
>      FAIL;
>
> Index: gcc/config/sh/sh.md
> ===================================================================
> --- gcc/config/sh/sh.md 2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/sh/sh.md 2013-11-05 08:56:11.554792175 +0000
> @@ -8775,25 +8775,21 @@ (define_split
>  })
>
>  ; operand 0 is the loop count pseudo register
> -; operand 1 is the number of loop iterations or 0 if it is unknown
> -; 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 1 is the label to jump to at the top of the loop
>  (define_expand "doloop_end"
>    [(parallel [(set (pc)
>                    (if_then_else (ne:SI (match_operand:SI 0 "" "")
>                                         (const_int 1))
> -                                (label_ref (match_operand 4 "" ""))
> +                                (label_ref (match_operand 1 "" ""))
>                                  (pc)))
>               (set (match_dup 0)
>                    (plus:SI (match_dup 0) (const_int -1)))
> -             (clobber (reg:SI T_REG))])
> -   (match_operand 5 "" "")]
> +             (clobber (reg:SI T_REG))])]
>    "TARGET_SH2"
>  {
>    if (GET_MODE (operands[0]) != SImode)
>      FAIL;
> -  emit_jump_insn (gen_doloop_end_split (operands[0], operands[4], operands[0]));
> +  emit_jump_insn (gen_doloop_end_split (operands[0], operands[1], operands[0]));
>    DONE;
>  })
>
> Index: gcc/config/spu/spu.md
> ===================================================================
> --- gcc/config/spu/spu.md       2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/spu/spu.md       2013-11-05 08:56:11.593792586 +0000
> @@ -4487,11 +4487,7 @@ (define_insn "dsync"
>   ;; knows what to generate.
>   (define_expand "doloop_end"
>     [(use (match_operand 0 "" ""))      ; loop pseudo
> -    (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
> -    (match_operand 5 "" "")]
> +    (use (match_operand 1 "" ""))]     ; label
>     ""
>     "
>   {
> @@ -4507,16 +4503,13 @@ (define_insn "dsync"
>       rtx bcomp;
>       rtx loc_ref;
>
> -     /* Only use this on innermost loops.  */
> -     if (INTVAL (operands[3]) > 1)
> -       FAIL;
>       if (GET_MODE (operands[0]) != SImode)
>         FAIL;
>
>       s0 = operands [0];
>       emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1)));
>       bcomp = gen_rtx_NE(SImode, s0, const0_rtx);
> -     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
> +     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
>       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
>                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
>                                                          loc_ref, pc_rtx)));
> Index: gcc/config/spu/spu.c
> ===================================================================
> --- gcc/config/spu/spu.c        2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/spu/spu.c        2013-11-05 08:56:11.592792578 +0000
> @@ -7328,6 +7328,9 @@ #define TARGET_DELAY_VARTRACK true
>  #undef TARGET_CANONICALIZE_COMPARISON
>  #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
>
> +#undef TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
> +
>  struct gcc_target targetm = TARGET_INITIALIZER;
>
>  #include "gt-spu.h"
> Index: gcc/config/tilegx/tilegx.md
> ===================================================================
> --- gcc/config/tilegx/tilegx.md 2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/tilegx/tilegx.md 2013-11-05 08:56:11.595792600 +0000
> @@ -2414,11 +2414,7 @@ (define_expand "udivsi3"
>  ;; generate.
>  (define_expand "doloop_end"
>    [(use (match_operand 0 "" ""))    ;; loop pseudo
> -   (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 5 "" ""))]   ;; flag: 1 if loop entered at top, else 0
> +   (use (match_operand 1 "" ""))]   ;; label
>     ""
>  {
>    if (optimize > 0 && flag_modulo_sched)
> @@ -2428,9 +2424,6 @@ (define_expand "doloop_end"
>       rtx loc_ref;
>       enum machine_mode mode = GET_MODE (operands[0]);
>
> -     /* only do inner loop  */
> -     if (INTVAL (operands[3]) > 1)
> -       FAIL;
>       /* only deal with loop counters in SImode or DImode  */
>       if (mode != SImode && mode != DImode)
>         FAIL;
> @@ -2438,7 +2431,7 @@ (define_expand "doloop_end"
>       s0 = operands [0];
>       emit_move_insn (s0, gen_rtx_PLUS (mode, s0, GEN_INT (-1)));
>       bcomp = gen_rtx_NE(mode, s0, const0_rtx);
> -     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
> +     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
>       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
>                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
>                                                          loc_ref, pc_rtx)));
> Index: gcc/config/tilegx/tilegx.c
> ===================================================================
> --- gcc/config/tilegx/tilegx.c  2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/tilegx/tilegx.c  2013-11-05 08:56:11.594792593 +0000
> @@ -5578,6 +5578,8 @@ #define TARGET_ASM_FILE_END tilegx_file_
>  #undef  TARGET_ASM_ALIGNED_DI_OP
>  #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
>
> +#undef  TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
>
>  struct gcc_target targetm = TARGET_INITIALIZER;
>
> Index: gcc/config/tilepro/tilepro.md
> ===================================================================
> --- gcc/config/tilepro/tilepro.md       2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/tilepro/tilepro.md       2013-11-05 08:56:11.597792621 +0000
> @@ -1318,11 +1318,7 @@ (define_expand "umulsi3_highpart"
>  ;; generate.
>  (define_expand "doloop_end"
>    [(use (match_operand 0 "" ""))    ;; loop pseudo
> -   (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 5 "" ""))]   ;; flag: 1 if loop entered at top, else 0
> +   (use (match_operand 1 "" ""))]   ;; label
>     ""
>  {
>    if (optimize > 0)
> @@ -1331,9 +1327,6 @@ (define_expand "doloop_end"
>       rtx bcomp;
>       rtx loc_ref;
>
> -     /* only do inner loop  */
> -     if (INTVAL (operands[3]) > 1)
> -       FAIL;
>       /* only deal with loop counters in SImode  */
>       if (GET_MODE (operands[0]) != SImode)
>         FAIL;
> @@ -1342,7 +1335,7 @@ (define_expand "doloop_end"
>
>       emit_move_insn (s0, gen_rtx_PLUS (SImode, s0, GEN_INT (-1)));
>       bcomp = gen_rtx_NE(SImode, s0, const0_rtx);
> -     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [4]);
> +     loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands [1]);
>       emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
>                                    gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
>                                                          loc_ref, pc_rtx)));
> Index: gcc/config/tilepro/tilepro.c
> ===================================================================
> --- gcc/config/tilepro/tilepro.c        2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/tilepro/tilepro.c        2013-11-05 08:56:11.596792609 +0000
> @@ -5067,6 +5067,8 @@ #define TARGET_PRINT_OPERAND_ADDRESS til
>  #undef  TARGET_ASM_FILE_END
>  #define TARGET_ASM_FILE_END tilepro_file_end
>
> +#undef  TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
>
>  struct gcc_target targetm = TARGET_INITIALIZER;
>
> Index: gcc/config/v850/v850.md
> ===================================================================
> --- gcc/config/v850/v850.md     2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/v850/v850.md     2013-11-05 08:56:11.599792647 +0000
> @@ -1357,20 +1357,11 @@ (define_insn "*rotlsi3_16"
>
>  (define_expand "doloop_begin"
>   [(use (match_operand 0 "" ""))        ; loop pseudo
> -  (use (match_operand 1 "" ""))        ; iterations; zero if unknown
> -  (use (match_operand 2 "" ""))        ; max iterations
> -  (use (match_operand 3 "" ""))        ; loop level
> -  (use (match_operand 4 "" ""))]       ; condition
> +  (use (match_operand 1 "" ""))]       ; doloop_end pattern
>    "TARGET_V850E3V5_UP && TARGET_LOOP"
>    {
> -    rtx loop_cnt   = operands[0];
> -    rtx loop_level = operands[3];
> -
> -    if (INTVAL (loop_level) > 1)
> -      FAIL;
> -    if (GET_MODE (loop_cnt) != SImode)
> -      FAIL;
> -
> +    rtx loop_cnt = operands[0];
> +    gcc_assert (GET_MODE (loop_cnt) == SImode);
>      emit_insn (gen_fix_loop_counter (loop_cnt));
>      DONE;
>    }
> @@ -1394,19 +1385,12 @@ (define_insn "fix_loop_counter"
>
>  (define_expand "doloop_end"
>   [(use (match_operand 0 "" ""))        ; loop pseudo
> -  (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 5 "" ""))]       ; entered at top
> +  (use (match_operand 1 "" ""))]       ; label
>    "TARGET_V850E3V5_UP && TARGET_LOOP"
>    {
> -    rtx loop_cnt   = operands[0];
> -    rtx loop_level = operands[3];
> -    rtx label      = operands[4];
> +    rtx loop_cnt = operands[0];
> +    rtx label    = operands[1];
>
> -    if (INTVAL (loop_level) > 1)
> -      FAIL;
>      if (GET_MODE (loop_cnt) != SImode)
>        FAIL;
>
> Index: gcc/config/v850/v850.c
> ===================================================================
> --- gcc/config/v850/v850.c      2013-11-05 08:55:57.423644646 +0000
> +++ gcc/config/v850/v850.c      2013-11-05 08:56:11.598792634 +0000
> @@ -3269,6 +3269,9 @@ #define TARGET_TRAMPOLINE_INIT v850_tram
>  #undef  TARGET_LEGITIMATE_CONSTANT_P
>  #define TARGET_LEGITIMATE_CONSTANT_P v850_legitimate_constant_p
>
> +#undef  TARGET_CAN_USE_DOLOOP_P
> +#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
> +
>  struct gcc_target targetm = TARGET_INITIALIZER;
>
>  #include "gt-v850.h"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]