[PATCH] cleanups to -fprefetch-loop-arrays code in loop.c

Janis Johnson janis187@us.ibm.com
Fri May 10 13:24:00 GMT 2002


This patch changes the dump messages for -fprefetch-loop-arrays and
cleans up a few things, but makes absolutely no difference to the
generated code.  I've got some changes coming after this that will
affect the code, but want to get this stuff out of the way first.

The renamed macro isn't yet used anywhere else.

Bootstrapped and tested on i686-pc-linux-gnu.  I also started a cross
build for mips-elf, which doesn't support prefetch, to check that I
didn't break builds for such targets; it's not finished, but it compiled
loop.c.

2002-05-10  Janis Johnson  <janis187@us.ibm.com>

	* loop.c: (PREFETCH_EXTREME_DIFFERENCE, PREFETCH_BEFORE_LOOP): New.
	(PREFETCH_CONDITIONAL): Renamed from PREFETCH_NOT_ALWAYS.
	(struct prefetch_info): Fix spelling of member bytes_accessed.
	(emit_prefetch_instructions): Make dump messages more regular;
	restructure code to add more dump messages; use new macros for
	heuristics. (There are no code generation changes in any of this).

Index: loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.399
diff -u -p -r1.399 loop.c
--- loop.c	24 Apr 2002 23:52:16 -0000	1.399
+++ loop.c	10 May 2002 17:34:28 -0000
@@ -124,14 +124,26 @@ Software Foundation, 59 Temple Place - S
 #define PREFETCH_EXTREME_STRIDE 4096
 #endif
 
+/* Define a limit to how far apart indices can be and still be merged
+   into a single prefetch.  */
+#ifndef PREFETCH_EXTREME_DIFFERENCE
+#define PREFETCH_EXTREME_DIFFERENCE 4096
+#endif
+
+/* Issue prefetch instructions before the loop to fetch data to be used
+   in the first few loop iterations.  */
+#ifndef PREFETCH_BEFORE_LOOP
+#define PREFETCH_BEFORE_LOOP 1
+#endif
+
 /* Do not handle reversed order prefetches (negative stride).  */
 #ifndef PREFETCH_NO_REVERSE_ORDER
 #define PREFETCH_NO_REVERSE_ORDER 1
 #endif
 
-/* Prefetch even if the GIV is not always executed.  */
-#ifndef PREFETCH_NOT_ALWAYS
-#define PREFETCH_NOT_ALWAYS 0
+/* Prefetch even if the GIV is in conditional code.  */
+#ifndef PREFETCH_CONDITIONAL
+#define PREFETCH_CONDITIONAL 0
 #endif
 
 /* If the loop requires more prefetches than the target can process in
@@ -3569,7 +3581,7 @@ struct prefetch_info
   HOST_WIDE_INT index;
   HOST_WIDE_INT stride;		/* Prefetch stride in bytes in each
 				   iteration.  */
-  unsigned int bytes_accesed;	/* Sum of sizes of all acceses to this
+  unsigned int bytes_accessed;	/* Sum of sizes of all acceses to this
 				   prefetch area in one iteration.  */
   unsigned int total_bytes;	/* Total bytes loop will access in this block.
 				   This is set only for loops with known
@@ -3781,18 +3793,19 @@ emit_prefetch_instructions (loop)
   if (PREFETCH_NO_CALL && LOOP_INFO (loop)->has_call)
     {
       if (loop_dump_stream)
-	fprintf (loop_dump_stream, "Prefetch: ignoring loop - has call.\n");
+	fprintf (loop_dump_stream, "Prefetch: ignoring loop: has call.\n");
 
       return;
     }
 
+  /* Don't prefetch in loops known to have few iterations.  */
   if (PREFETCH_NO_LOW_LOOPCNT
       && LOOP_INFO (loop)->n_iterations
       && LOOP_INFO (loop)->n_iterations <= PREFETCH_LOW_LOOPCNT)
     {
       if (loop_dump_stream)
 	fprintf (loop_dump_stream,
-		 "Prefetch: ignoring loop - not enought iterations.\n");
+		 "Prefetch: ignoring loop: not enough iterations.\n");
       return;
     }
 
@@ -3813,14 +3826,13 @@ emit_prefetch_instructions (loop)
 	     BIVs that are executed multiple times; such BIVs ought to be
 	     handled in the nested loop.  We accept not_every_iteration BIVs,
 	     since these only result in larger strides and make our
-	     heuristics more conservative.
-	     ??? What does the last sentence mean?  */
+	     heuristics more conservative.  */
 	  if (GET_CODE (biv->add_val) != CONST_INT)
 	    {
 	      if (loop_dump_stream)
 		{
 		  fprintf (loop_dump_stream,
-			   "Prefetch: biv %i ignored: non-constant addition at insn %i:",
+		    "Prefetch: ignoring biv %d: non-constant addition at insn %d:",
 			   REGNO (biv->src_reg), INSN_UID (biv->insn));
 		  print_rtl (loop_dump_stream, biv->add_val);
 		  fprintf (loop_dump_stream, "\n");
@@ -3833,7 +3845,7 @@ emit_prefetch_instructions (loop)
 	      if (loop_dump_stream)
 		{
 		  fprintf (loop_dump_stream,
-			   "Prefetch: biv %i ignored: maybe_multiple at insn %i:",
+			   "Prefetch: ignoring biv %d: maybe_multiple at insn %i:",
 			   REGNO (biv->src_reg), INSN_UID (biv->insn));
 		  print_rtl (loop_dump_stream, biv->add_val);
 		  fprintf (loop_dump_stream, "\n");
@@ -3854,41 +3866,64 @@ emit_prefetch_instructions (loop)
 	  rtx temp;
 	  HOST_WIDE_INT index = 0;
 	  int add = 1;
-	  HOST_WIDE_INT stride;
+	  HOST_WIDE_INT stride = 0;
+	  int stride_sign = 1;
 	  struct check_store_data d;
+	  const char *ignore_reason = NULL;
 	  int size = GET_MODE_SIZE (GET_MODE (iv));
 
-	  /* There are several reasons why an induction variable is not
-	     interesting to us.  */
-	  if (iv->giv_type != DEST_ADDR
-	      /* We are interested only in constant stride memory references
-		 in order to be able to compute density easily.  */
-	      || GET_CODE (iv->mult_val) != CONST_INT
-	      /* Don't handle reversed order prefetches, since they are usually
-		 ineffective.  Later we may be able to reverse such BIVs.  */
-	      || (PREFETCH_NO_REVERSE_ORDER
-		  && (stride = INTVAL (iv->mult_val) * basestride) < 0)
-	      /* Prefetching of accesses with such an extreme stride is probably
-		 not worthwhile, either.  */
-	      || (PREFETCH_NO_EXTREME_STRIDE
-		  && stride > PREFETCH_EXTREME_STRIDE)
+	  /* See whether an induction variable is interesting to us and if
+	     not, report the reason.  */
+	  if (iv->giv_type != DEST_ADDR)
+	    ignore_reason = "giv is not a destination address";
+
+	  /* We are interested only in constant stride memory references
+	     in order to be able to compute density easily.  */
+	  else if (GET_CODE (iv->mult_val) != CONST_INT)
+	    ignore_reason = "stride is not constant";
+
+	  else
+	    {
+	      stride = INTVAL (iv->mult_val) * basestride;
+	      if (stride < 0)
+	        {
+		  stride = -stride;
+		  stride_sign = -1;
+	        }
+
+	      /* On some targets, reversed order prefetches are not
+	         worthwhile.  */
+	      if (PREFETCH_NO_REVERSE_ORDER && stride_sign < 0)
+		ignore_reason = "reversed order stride";
+
+	      /* Prefetch of accesses with an extreme stride might not be
+	         worthwhile, either.  */
+	      else if (PREFETCH_NO_EXTREME_STRIDE
+		       && stride > PREFETCH_EXTREME_STRIDE)
+		ignore_reason = "extreme stride";
+
 	      /* Ignore GIVs with varying add values; we can't predict the
-		 value for the next iteration.  */
-	      || !loop_invariant_p (loop, iv->add_val)
+	         value for the next iteration.  */
+	      else if (!loop_invariant_p (loop, iv->add_val))
+		ignore_reason = "giv has varying add value";
+
 	      /* Ignore GIVs in the nested loops; they ought to have been
-		 handled already.  */
-	      || iv->maybe_multiple)
+	         handled already.  */
+	      else if (iv->maybe_multiple)
+		ignore_reason = "giv is in nested loop";
+	    }
+
+	  if (ignore_reason != NULL)
 	    {
 	      if (loop_dump_stream)
-		fprintf (loop_dump_stream, "Prefetch: Ignoring giv at %i\n",
-			 INSN_UID (iv->insn));
+		fprintf (loop_dump_stream,
+			 "Prefetch: ignoring giv at %d: %s.\n",
+			 INSN_UID (iv->insn), ignore_reason);
 	      continue;
 	    }
 
 	  /* Determine the pointer to the basic array we are examining.  It is
 	     the sum of the BIV's initial value and the GIV's add_val.  */
-	  index = 0;
-
 	  address = copy_rtx (iv->add_val);
 	  temp = copy_rtx (bl->initial_value);
 
@@ -3901,7 +3936,7 @@ emit_prefetch_instructions (loop)
 
 	  /* When the GIV is not always executed, we might be better off by
 	     not dirtying the cache pages.  */
-	  if (PREFETCH_NOT_ALWAYS || iv->always_executed)
+	  if (PREFETCH_CONDITIONAL || iv->always_executed)
 	    note_stores (PATTERN (iv->insn), check_store, &d);
 
 	  /* Attempt to find another prefetch to the same array and see if we
@@ -3914,13 +3949,14 @@ emit_prefetch_instructions (loop)
 		   just with small difference in constant indexes), merge
 		   the prefetches.  Just do the later and the earlier will
 		   get prefetched from previous iteration.
-		   4096 is artificial threshold.  It should not be too small,
+		   The artificial threshold should not be too small,
 		   but also not bigger than small portion of memory usually
 		   traversed by single loop.  */
-		if (index >= info[i].index && index - info[i].index < 4096)
+		if (index >= info[i].index
+		    && index - info[i].index < PREFETCH_EXTREME_DIFFERENCE)
 		  {
 		    info[i].write |= d.mem_write;
-		    info[i].bytes_accesed += size;
+		    info[i].bytes_accessed += size;
 		    info[i].index = index;
 		    info[i].giv = iv;
 		    info[i].class = bl;
@@ -3929,10 +3965,11 @@ emit_prefetch_instructions (loop)
 		    break;
 		  }
 
-		if (index < info[i].index && info[i].index - index < 4096)
+		if (index < info[i].index
+		    && info[i].index - index < PREFETCH_EXTREME_DIFFERENCE)
 		  {
 		    info[i].write |= d.mem_write;
-		    info[i].bytes_accesed += size;
+		    info[i].bytes_accessed += size;
 		    add = 0;
 		    break;
 		  }
@@ -3947,7 +3984,7 @@ emit_prefetch_instructions (loop)
 	      info[num_prefetches].stride = stride;
 	      info[num_prefetches].base_address = address;
 	      info[num_prefetches].write = d.mem_write;
-	      info[num_prefetches].bytes_accesed = size;
+	      info[num_prefetches].bytes_accessed = size;
 	      num_prefetches++;
 	      if (num_prefetches >= MAX_PREFETCHES)
 		{
@@ -3962,8 +3999,10 @@ emit_prefetch_instructions (loop)
 
   for (i = 0; i < num_prefetches; i++)
     {
-      /* Attempt to calculate the number of bytes fetched by the loop.
-	 Avoid overflow.  */
+      int density;
+
+      /* Attempt to calculate the total number of bytes fetched by all
+	 iterations of the loop.  Avoid overflow.  */
       if (LOOP_INFO (loop)->n_iterations
           && ((unsigned HOST_WIDE_INT) (0xffffffff / info[i].stride)
 	      >= LOOP_INFO (loop)->n_iterations))
@@ -3971,19 +4010,29 @@ emit_prefetch_instructions (loop)
       else
 	info[i].total_bytes = 0xffffffff;
 
-      /* Prefetch is worthwhile only when the loads/stores are dense.  */
-      if (PREFETCH_ONLY_DENSE_MEM
-	  && info[i].bytes_accesed * 256 / info[i].stride > PREFETCH_DENSE_MEM
-	  && (info[i].total_bytes / PREFETCH_BLOCK
-	      >= PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
-	{
-	  info[i].prefetch_before_loop = 1;
-	  info[i].prefetch_in_loop
-	    = (info[i].total_bytes / PREFETCH_BLOCK
-	       > PREFETCH_BLOCKS_BEFORE_LOOP_MAX);
-	}
+      density = info[i].bytes_accessed * 100 / info[i].stride;
+
+      /* Prefetch might be worthwhile only when the loads/stores are dense.  */
+      if (PREFETCH_ONLY_DENSE_MEM)
+	if (density * 256 > PREFETCH_DENSE_MEM * 100
+	    && (info[i].total_bytes / PREFETCH_BLOCK
+	        >= PREFETCH_BLOCKS_BEFORE_LOOP_MIN))
+	  {
+	    info[i].prefetch_before_loop = 1;
+	    info[i].prefetch_in_loop
+	      = (info[i].total_bytes / PREFETCH_BLOCK
+	         > PREFETCH_BLOCKS_BEFORE_LOOP_MAX);
+	  }
+        else
+	  {
+	    info[i].prefetch_in_loop = 0, info[i].prefetch_before_loop = 0;
+	    if (loop_dump_stream)
+	      fprintf (loop_dump_stream,
+		  "Prefetch: ignoring giv at %d: %d%% density is too low.\n",
+		       INSN_UID (info[i].giv->insn), density);
+	  }
       else
-        info[i].prefetch_in_loop = 0, info[i].prefetch_before_loop = 0;
+	info[i].prefetch_in_loop = 1, info[i].prefetch_before_loop = 1;
 
       if (info[i].prefetch_in_loop)
 	{
@@ -3999,23 +4048,30 @@ emit_prefetch_instructions (loop)
     {
       for (i = 0; i < num_prefetches; i++)
 	{
-	  fprintf (loop_dump_stream, "Prefetch insn %i address: ",
+	  if (info[i].prefetch_in_loop == 0
+	      && info[i].prefetch_before_loop == 0)
+	    continue;
+	  fprintf (loop_dump_stream, "Prefetch insn: %d",
 		   INSN_UID (info[i].giv->insn));
-	  print_rtl (loop_dump_stream, info[i].base_address);
-	  fprintf (loop_dump_stream, " Index: ");
-	  fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].index);
-	  fprintf (loop_dump_stream, " stride: ");
-	  fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].stride);
 	  fprintf (loop_dump_stream,
-		   " density: %i%% total_bytes: %u%sin loop: %s before: %s\n",
-		   (int) (info[i].bytes_accesed * 100 / info[i].stride),
-		   info[i].total_bytes,
-		   info[i].write ? " read/write " : " read only ",
+		   "; in loop: %s; before: %s; %s\n",
 		   info[i].prefetch_in_loop ? "yes" : "no",
-		   info[i].prefetch_before_loop ? "yes" : "no");
+		   info[i].prefetch_before_loop ? "yes" : "no",
+		   info[i].write ? "read/write" : "read only");
+	  fprintf (loop_dump_stream,
+		   " density: %d%%; bytes_accessed: %u; total_bytes: %u\n",
+		   (int) (info[i].bytes_accessed * 100 / info[i].stride),
+		   info[i].bytes_accessed, info[i].total_bytes);
+	  fprintf (loop_dump_stream, " index: ");
+	  fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].index);
+	  fprintf (loop_dump_stream, "; stride: ");
+	  fprintf (loop_dump_stream, HOST_WIDE_INT_PRINT_DEC, info[i].stride);
+	  fprintf (loop_dump_stream, "; address: ");
+	  print_rtl (loop_dump_stream, info[i].base_address);
+	  fprintf (loop_dump_stream, "\n");
 	}
 
-      fprintf (loop_dump_stream, "Real prefetches needed: %i (write: %i)\n",
+      fprintf (loop_dump_stream, "Real prefetches needed: %d (write: %d)\n",
 	       num_real_prefetches, num_real_write_prefetches);
     }
 
@@ -4024,8 +4080,14 @@ emit_prefetch_instructions (loop)
 
   ahead = SIMULTANEOUS_PREFETCHES / num_real_prefetches;
 
-  if (!ahead)
-    return;
+  if (ahead == 0)
+    {
+      if (loop_dump_stream)
+	fprintf (loop_dump_stream,
+		 "Prefetch: ignoring loop: ahead is zero; %d < %d\n",
+		 SIMULTANEOUS_PREFETCHES, num_real_prefetches);
+      return;
+    }
 
   for (i = 0; i < num_prefetches; i++)
     {
@@ -4077,7 +4139,7 @@ emit_prefetch_instructions (loop)
 	    }
 	}
 
-      if (info[i].prefetch_before_loop)
+      if (PREFETCH_BEFORE_LOOP && info[i].prefetch_before_loop)
 	{
 	  int y;
 



More information about the Gcc-patches mailing list