On Tue, Nov 5, 2013 at 10:33 AM, Richard Sandiford <rdsandif...@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"