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]

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


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