https://gcc.gnu.org/bugzilla/show_bug.cgi?id=72855
--- Comment #4 from amker at gcc dot gnu.org --- Here is a simple refactoring patch. diff --git a/gcc/loop-doloop.c b/gcc/loop-doloop.c index c311516..9fb04cf 100644 --- a/gcc/loop-doloop.c +++ b/gcc/loop-doloop.c @@ -254,18 +254,51 @@ doloop_condition_get (rtx doloop_pat) return 0; } -/* Return nonzero if the loop specified by LOOP is suitable for - the use of special low-overhead looping instructions. DESC - describes the number of iterations of the loop. */ +/* Check all insns of LOOP to see if the loop is suitable for the use of + special low-overhead looping instructions. Return TRUE if yes, false + otherwise. */ static bool -doloop_valid_p (struct loop *loop, struct niter_desc *desc) +doloop_insn_valid_p (struct loop *loop) { - basic_block *body = get_loop_body (loop), bb; - rtx_insn *insn; unsigned i; - bool result = true; + rtx_insn *insn; + basic_block *body = get_loop_body (loop), bb; + for (i = 0; i < loop->num_nodes; i++) + { + bb = body[i]; + + for (insn = BB_HEAD (bb); + insn != NEXT_INSN (BB_END (bb)); + insn = NEXT_INSN (insn)) + { + /* Different targets have different necessities for low-overhead + looping. Call the back end for each instruction within the loop + to let it decide whether the insn prohibits a low-overhead loop. + It will then return the cause for it to emit to the dump file. */ + const char * invalid = targetm.invalid_within_doloop (insn); + if (invalid) + { + if (dump_file) + fprintf (dump_file, "Doloop: %s\n", invalid); + + free (body); + return false; + } + } + } + free (body); + return true; +} + +/* Check the number of iterations described by DESC of a loop to see if + the loop is suitable for the use of special low-overhead looping + instructions. Return true if yes, false otherwise. */ + +static bool +doloop_niter_valid_p (struct loop *, struct niter_desc *desc) +{ /* Check for loops that may not terminate under special conditions. */ if (!desc->simple_p || desc->assumptions @@ -295,38 +328,10 @@ doloop_valid_p (struct loop *loop, struct niter_desc *desc) enable count-register loops in this case. */ if (dump_file) fprintf (dump_file, "Doloop: Possible infinite iteration case.\n"); - result = false; - goto cleanup; - } - - for (i = 0; i < loop->num_nodes; i++) - { - bb = body[i]; - - for (insn = BB_HEAD (bb); - insn != NEXT_INSN (BB_END (bb)); - insn = NEXT_INSN (insn)) - { - /* Different targets have different necessities for low-overhead - looping. Call the back end for each instruction within the loop - to let it decide whether the insn prohibits a low-overhead loop. - It will then return the cause for it to emit to the dump file. */ - const char * invalid = targetm.invalid_within_doloop (insn); - if (invalid) - { - if (dump_file) - fprintf (dump_file, "Doloop: %s\n", invalid); - result = false; - goto cleanup; - } - } + return false; } - result = true; - -cleanup: - free (body); - return result; + return true; } /* Adds test of COND jumping to DEST on edge *E and set *E to the new fallthru @@ -621,17 +626,25 @@ doloop_optimize (struct loop *loop) if (dump_file) fprintf (dump_file, "Doloop: Processing loop %d.\n", loop->num); + if (!doloop_insn_valid_p (loop)) + { + if (dump_file) + fprintf (dump_file, "Doloop: The loop is not suitable.\n"); + + return false; + } + iv_analysis_loop_init (loop); /* Find the simple exit of a LOOP. */ desc = get_simple_loop_desc (loop); /* Check that loop is a candidate for a low-overhead looping insn. */ - if (!doloop_valid_p (loop, desc)) + if (!doloop_niter_valid_p (loop, desc)) { if (dump_file) - fprintf (dump_file, - "Doloop: The loop is not suitable.\n"); + fprintf (dump_file, "Doloop: The loop is not suitable.\n"); + return false; } mode = desc->mode; It reduces compile time for powerpc-elf on x86_64 machine from 54m to 5m. The compiler is configured with checking. With "--enable-checking=release", the current trunk compiles for ~5m too, but gcc in Ubuntu has the issue even it's configured as release?