#! /bin/sh -e if [ $# -eq 3 -a "$2" = '-d' ]; then pdir="-d $3" elif [ $# -ne 1 ]; then echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 fi case "$1" in -patch) patch $pdir -f --no-backup-if-mismatch -p0 < $0;; -unpatch) patch $pdir -f --no-backup-if-mismatch -R -p0 < $0;; *) echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 esac exit 0 # DP: From: Alan Modra Sender: gcc-patches-owner@gcc.gnu.org # DP: To: gcc-patches@gcc.gnu.org Cc: Paul Mackerras , Olaf Hering # DP: Subject: gcc-2.95 strength reduction fix # DP: Date: Mon, 3 Dec 2001 14:51:31 +1030 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); } --- # DP: This particular problem was fixed on the mainline by # DP: http://gcc.gnu.org/ml/gcc-patches/2000-04/msg00576.html, which is a # DP: much nicer fix than the following but a minimal change may be preferred # DP: for the 2.95 branch. # DP: # DP: * loop.c (strength_reduce ): Set up maybe_multiple for givs. # DP: (record_giv): Pass in maybe_multiple. # DP: (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 --- gcc/loop.c 2001/04/03 12:09:42 1.156.4.21 +++ gcc/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 *)); @@ -4426,6 +4427,7 @@ strength_reduce (scan_start, end, loop_t biv and a constant (or invariant), and it is not a biv. */ not_every_iteration = 0; + maybe_multiple = 0; loop_depth = 0; p = scan_start; while (1) @@ -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; In-Reply-To: <20011203145131.C1047@bubble.sa.bigpond.net.au>; from amodra@bigpond.net.au on Mon, Dec 03, 2001 at 02:51:31PM +1030 From: Alan Modra Sender: gcc-patches-owner@gcc.gnu.org To: gcc-patches@gcc.gnu.org, Paul Mackerras , Olaf Hering Subject: Re: gcc-2.95 strength reduction fix Date: Mon, 3 Dec 2001 17:17:11 +1030 On Mon, Dec 03, 2001 at 02:51:31PM +1030, Alan Modra wrote: > > * loop.c (strength_reduce ): Set up maybe_multiple for givs. > (record_giv): Pass in maybe_multiple. > (find_mem_givs): Likewise. Sorry, needs this hunk too. [inserted above]