This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
gcc-2.95 strength reduction fix
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Paul Mackerras <paulus at au1 dot ibm dot com>, Olaf Hering <olh at suse dot de>
- Date: Mon, 3 Dec 2001 14:51:31 +1030
- Subject: 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;