This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
powerpc64 doloop not used in all loops?
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc at gcc dot gnu dot org
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 20 Sep 2002 12:08:35 +0930
- Subject: powerpc64 doloop not used in all loops?
This testcase:
#define NR_RUNS 100000
void foo (void)
{
unsigned long i;
i = NR_RUNS;
do { } while (--i);
i = NR_RUNS;
do { } while (--i);
}
generates this code on powerpc64:
.foo:
lis 0,0x1
ori 0,0,34464
mtctr 0
.L11:
bdnz .L11
lis 0,0x1
ori 0,0,34464
.L10:
addic. 0,0,-1
bne+ 0,.L10
blr
Note the lack of "bdnz" on the second loop. It seems to be a global
register allocation problem, and curiously, setting NR_RUNS to 100
or any other value that can be loaded into a reg in one instruction
avoids the problem. So my patch below might be papering over the
real problem. On the other hand, it's probably a good idea to
keep the number of registers down.
gcc/ChangeLog
* doloop.c (doloop_optimize): Reuse previous doloop_reg.
* loop.c (loop_optimize): Pass "loops" to scan_loop.
(scan_loop): And from there to strength_reduce.
(strength_reduce): And finally to doloop_optimize.
Adjust prototypes.
* loop.h (struct loop_info): Add doloop_reg field.
(doloop_optimize): Adjust prototype.
Bootstrapped and regression tested powerpc-linux, on the 3.2 branch
because I was getting compare failures on mainline. :(
diff -urpN -xCVS -x'*~' -x'*.info*' -x'*.[17]' -xTAGS gcc-ppc64-32.orig/gcc/doloop.c gcc-ppc64-32/gcc/doloop.c
--- gcc-ppc64-32.orig/gcc/doloop.c 2002-09-13 20:50:47.000000000 +0930
+++ gcc-ppc64-32/gcc/doloop.c 2002-09-19 19:09:36.000000000 +0930
@@ -752,7 +752,8 @@ doloop_modify_runtime (loop, iterations_
is a candidate for this optimization. Returns non-zero if loop
successfully modified. */
int
-doloop_optimize (loop)
+doloop_optimize (loops, loop)
+ const struct loops *loops;
const struct loop *loop;
{
struct loop_info *loop_info = LOOP_INFO (loop);
@@ -768,6 +769,7 @@ doloop_optimize (loop)
rtx iterations_max;
rtx start_label;
rtx condition;
+ const struct loop *prev;
if (loop_dump_stream)
fprintf (loop_dump_stream,
@@ -841,7 +843,20 @@ doloop_optimize (loop)
to modify the loop since there is some aspect the back-end does
not like. */
start_label = gen_label_rtx ();
- doloop_reg = gen_reg_rtx (mode);
+ doloop_reg = NULL_RTX;
+ for (prev = loop; ++prev < &loops->array[loops->num]; )
+ {
+ struct loop_info *prev_info = LOOP_INFO (prev);
+ if (prev_info->iteration_var == loop_info->iteration_var)
+ {
+ doloop_reg = prev_info->doloop_reg;
+ if (doloop_reg)
+ break;
+ }
+ }
+ if (!doloop_reg)
+ doloop_reg = gen_reg_rtx (mode);
+ loop_info->doloop_reg = doloop_reg;
doloop_seq = gen_doloop_end (doloop_reg, iterations, iterations_max,
GEN_INT (loop->level), start_label);
if (! doloop_seq && mode != word_mode)
diff -urpN -xCVS -x'*~' -x'*.info*' -x'*.[17]' -xTAGS gcc-ppc64-32.orig/gcc/loop.c gcc-ppc64-32/gcc/loop.c
--- gcc-ppc64-32.orig/gcc/loop.c 2002-09-12 11:44:15.000000000 +0930
+++ gcc-ppc64-32/gcc/loop.c 2002-09-19 19:09:38.000000000 +0930
@@ -247,7 +247,7 @@ static void count_one_set PARAMS ((struc
static void note_addr_stored PARAMS ((rtx, rtx, void *));
static void note_set_pseudo_multiple_uses PARAMS ((rtx, rtx, void *));
static int loop_reg_used_before_p PARAMS ((const struct loop *, rtx, rtx));
-static void scan_loop PARAMS ((struct loop*, int));
+static void scan_loop PARAMS ((const struct loops *, struct loop *, int));
#if 0
static void replace_call_address PARAMS ((rtx, rtx, rtx));
#endif
@@ -282,7 +282,7 @@ static void loop_givs_reduce PARAMS((str
static void loop_givs_rescan PARAMS((struct loop *, struct iv_class *,
rtx *));
static void loop_ivs_free PARAMS((struct loop *));
-static void strength_reduce PARAMS ((struct loop *, int));
+static void strength_reduce PARAMS ((const struct loops *, struct loop *, int));
static void find_single_use_in_loop PARAMS ((struct loop_regs *, rtx, rtx));
static int valid_initial_value_p PARAMS ((rtx, rtx, int, rtx));
static void find_mem_givs PARAMS ((const struct loop *, rtx, rtx, int, int));
@@ -550,7 +550,7 @@ loop_optimize (f, dumpfile, flags)
struct loop *loop = &loops->array[i];
if (! loop->invalid && loop->end)
- scan_loop (loop, flags);
+ scan_loop (loops, loop, flags);
}
/* If there were lexical blocks inside the loop, they have been
@@ -608,7 +608,8 @@ next_insn_in_loop (loop, insn)
write, then we can also mark the memory read as invariant. */
static void
-scan_loop (loop, flags)
+scan_loop (loops, loop, flags)
+ const struct loops *loops;
struct loop *loop;
int flags;
{
@@ -1154,7 +1155,7 @@ scan_loop (loop, flags)
/* Ensure our label doesn't go away. */
LABEL_NUSES (update_end)++;
- strength_reduce (loop, flags);
+ strength_reduce (loops, loop, flags);
reg_scan_update (update_start, update_end, loop_max_reg);
loop_max_reg = max_reg_num ();
@@ -4933,7 +4934,8 @@ loop_ivs_free (loop)
must check regnos to make sure they are in bounds. */
static void
-strength_reduce (loop, flags)
+strength_reduce (loops, loop, flags)
+ const struct loops *loops ATTRIBUTE_UNUSED;
struct loop *loop;
int flags;
{
@@ -5223,7 +5225,7 @@ strength_reduce (loop, flags)
#ifdef HAVE_doloop_end
if (HAVE_doloop_end && (flags & LOOP_BCT) && flag_branch_on_count_reg)
- doloop_optimize (loop);
+ doloop_optimize (loops, loop);
#endif /* HAVE_doloop_end */
/* In case number of iterations is known, drop branch prediction note
diff -urpN -xCVS -x'*~' -x'*.info*' -x'*.[17]' -xTAGS gcc-ppc64-32.orig/gcc/loop.h gcc-ppc64-32/gcc/loop.h
--- gcc-ppc64-32.orig/gcc/loop.h 2002-09-13 17:37:53.000000000 +0930
+++ gcc-ppc64-32/gcc/loop.h 2002-09-19 19:09:37.000000000 +0930
@@ -331,6 +331,8 @@ struct loop_info
rtx final_equiv_value;
/* Register corresponding to iteration variable. */
rtx iteration_var;
+ /* Register used by doloop pattern. */
+ rtx doloop_reg;
/* Constant loop increment. */
rtx increment;
enum rtx_code comparison_code;
@@ -421,4 +423,4 @@ rtx loop_insn_sink PARAMS((const struct
rtx loop_insn_hoist PARAMS((const struct loop *, rtx));
/* Forward declarations for non-static functions declared in doloop.c. */
-int doloop_optimize PARAMS ((const struct loop *));
+int doloop_optimize PARAMS ((const struct loops *, const struct loop *));
--
Alan Modra
IBM OzLabs - Linux Technology Centre