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]

gcc-2.95 strength reduction fix


This test case, extracted from lomount.c, fails for powerpc-linux with
current 2.95 CVS at -O2.

---
#define SIZE(a) (sizeof(a)/sizeof(a[0]))

static char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
static char statbuf[20];

extern void exit (int);
extern void abort (void);
int sprintf (char *, const char *, ...);
int printf (const char *, ...);
int stat (char *, char *);
int open (char *);

char *
find_unused_loop_device (void)
{
  char dev[20];
  int i, j, fd;

  for (j = 0; j < SIZE (loop_formats); j++)
    {
      for (i = 0; i < 256; i++)
	{
	  sprintf (dev, loop_formats[j], i);
	  printf ("dev=%s i=%d j=%d\n", dev, i, j);
	  if (stat (dev, statbuf) != 0 || statbuf[0] != 0)
	    break;
	  fd = foo2 ("blah");
	  if (fd >= 0)
	    return "blah";
	}
    }
  return 0;
}

int sprintf (char *buf, const char *fmt, ...)
{
  if (fmt != loop_formats[0] && fmt != loop_formats[1])
    abort ();
  return 0;
}

int printf (const char *fmt, ...)
{
  return 0;
}

int stat (char *x, char *y)
{
  y[0] = 0;
  return 0;
}

int open (char *x)
{
  return -1;
}

int main (void)
{
  find_unused_loop_device ();
  exit (0);
}
---

This particular problem was fixed on the mainline by
http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00576.html, which is a
much nicer fix than the following but a minimal change may be preferred
for the 2.95 branch.

	* loop.c (strength_reduce <giv loop>): Set up maybe_multiple for givs.
	(record_giv): Pass in maybe_multiple.
	(find_mem_givs): Likewise.

Index: loop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/loop.c,v
retrieving revision 1.156.4.21
diff -u -p -r1.156.4.21 loop.c
--- loop.c	2001/04/03 12:09:42	1.156.4.21
+++ loop.c	2001/12/03 02:44:40
@@ -320,11 +320,12 @@ static int count_nonfixed_reads PROTO((r
 static void strength_reduce PROTO((rtx, rtx, rtx, int, rtx, rtx, rtx, int, int));
 static void find_single_use_in_loop PROTO((rtx, rtx, varray_type));
 static int valid_initial_value_p PROTO((rtx, rtx, int, rtx));
-static void find_mem_givs PROTO((rtx, rtx, int, rtx, rtx));
+static void find_mem_givs PROTO((rtx, rtx, int, int, rtx, rtx));
 static void record_biv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx *, int, int));
 static void check_final_value PROTO((struct induction *, rtx, rtx, 
 				     unsigned HOST_WIDE_INT));
-static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx, int, enum g_types, int, rtx *, rtx, rtx));
+static void record_giv PROTO((struct induction *, rtx, rtx, rtx, rtx, rtx,
+			      int, enum g_types, int, int, rtx *, rtx, rtx));
 static void update_giv_derive PROTO((rtx));
 static int basic_induction_var PROTO((rtx, enum machine_mode, rtx, rtx, rtx *, rtx *, rtx **));
 static rtx simplify_giv_expr PROTO((rtx, int *));
@@ -4445,6 +4446,40 @@ strength_reduce (scan_start, end, loop_t
 	    break;
 	}
 
+      if (GET_CODE (p) == CODE_LABEL)
+	{
+	  rtx insn = p;
+
+	  maybe_multiple = 0;
+
+	  while (1)
+	    {
+	      insn = NEXT_INSN (insn);
+	      if (insn == scan_start)
+		break;
+	      if (insn == end)
+		{
+		  if (loop_top != 0)
+		    insn = loop_top;
+		  else
+		    break;
+		  if (insn == scan_start)
+		    break;
+		}
+
+	      if (GET_CODE (insn) == JUMP_INSN
+		  && GET_CODE (PATTERN (insn)) != RETURN
+		  && (! condjump_p (insn)
+		      || (JUMP_LABEL (insn) != 0
+			  && JUMP_LABEL (insn) != scan_start
+			  && ! loop_insn_first_p (p, JUMP_LABEL (insn)))))
+		{
+		  maybe_multiple = 1;
+		  break;
+		}
+	    }
+	}
+
       /* Look for a general induction variable in a register.  */
       if (GET_CODE (p) == INSN
 	  && (set = single_set (p))
@@ -4495,8 +4530,8 @@ strength_reduce (scan_start, end, loop_t
 		p = last_consec_insn;
 
 	      record_giv (v, p, src_reg, dest_reg, mult_val, add_val, benefit,
-			  DEST_REG, not_every_iteration, NULL_PTR, loop_start,
-			  loop_end);
+			  DEST_REG, not_every_iteration, maybe_multiple,
+			  NULL_PTR, loop_start, loop_end);
 
 	    }
 	}
@@ -4506,8 +4541,8 @@ strength_reduce (scan_start, end, loop_t
       /* This resulted in worse code on a VAX 8600.  I wonder if it
 	 still does.  */
       if (GET_CODE (p) == INSN)
-	find_mem_givs (PATTERN (p), p, not_every_iteration, loop_start,
-		       loop_end);
+	find_mem_givs (PATTERN (p), p, not_every_iteration, maybe_multiple,
+		       loop_start, loop_end);
 #endif
 
       /* Update the status of whether giv can derive other givs.  This can
@@ -5246,10 +5285,12 @@ valid_initial_value_p (x, insn, call_see
    every loop iteration.  */
 
 static void
-find_mem_givs (x, insn, not_every_iteration, loop_start, loop_end)
+find_mem_givs (x, insn, not_every_iteration, maybe_multiple,
+	       loop_start, loop_end)
      rtx x;
      rtx insn;
      int not_every_iteration;
+     int maybe_multiple;
      rtx loop_start, loop_end;
 {
   register int i, j;
@@ -5297,7 +5338,7 @@ find_mem_givs (x, insn, not_every_iterat
 
 	    record_giv (v, insn, src_reg, addr_placeholder, mult_val,
 			add_val, benefit, DEST_ADDR, not_every_iteration,
-			&XEXP (x, 0), loop_start, loop_end);
+			maybe_multiple, &XEXP (x, 0), loop_start, loop_end);
 
 	    v->mem_mode = GET_MODE (x);
 	  }
@@ -5313,12 +5354,12 @@ find_mem_givs (x, insn, not_every_iterat
   fmt = GET_RTX_FORMAT (code);
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     if (fmt[i] == 'e')
-      find_mem_givs (XEXP (x, i), insn, not_every_iteration, loop_start,
-		     loop_end);
+      find_mem_givs (XEXP (x, i), insn, not_every_iteration, maybe_multiple,
+		     loop_start, loop_end);
     else if (fmt[i] == 'E')
       for (j = 0; j < XVECLEN (x, i); j++)
 	find_mem_givs (XVECEXP (x, i, j), insn, not_every_iteration,
-		       loop_start, loop_end);
+		       maybe_multiple, loop_start, loop_end);
 }
 
 /* Fill in the data about one biv update.
@@ -5440,7 +5481,8 @@ record_biv (v, insn, dest_reg, inc_val, 
 
 static void
 record_giv (v, insn, src_reg, dest_reg, mult_val, add_val, benefit,
-	    type, not_every_iteration, location, loop_start, loop_end)
+	    type, not_every_iteration, maybe_multiple,
+	    location, loop_start, loop_end)
      struct induction *v;
      rtx insn;
      rtx src_reg;
@@ -5449,6 +5491,7 @@ record_giv (v, insn, src_reg, dest_reg, 
      int benefit;
      enum g_types type;
      int not_every_iteration;
+     int maybe_multiple;
      rtx *location;
      rtx loop_start, loop_end;
 {
@@ -5466,7 +5509,7 @@ record_giv (v, insn, src_reg, dest_reg, 
   v->location = location;
   v->cant_derive = 0;
   v->combined_with = 0;
-  v->maybe_multiple = 0;
+  v->maybe_multiple = maybe_multiple;
   v->maybe_dead = 0;
   v->derive_adjustment = 0;
   v->same = 0;


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