From: Mark Mitchell Date: Sat, 18 Jul 1998 15:21:13 +0000 (+0000) Subject: loop.c (maybe_eliminate_biv_1): Avoid signed/unsigned comparison confusion when setti... X-Git-Tag: prereleases/egcs-1.1-prerelease~206 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fa68ae5b436211cbc6a4d9807bc461956798c6bb;p=thirdparty%2Fgcc.git loop.c (maybe_eliminate_biv_1): Avoid signed/unsigned comparison confusion when setting cc0. * loop.c (maybe_eliminate_biv_1): Avoid signed/unsigned comparison confusion when setting cc0. From-SVN: r21273 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 360fa628dbd0..ebbb1bdd39f6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +Sat Jul 18 15:20:19 1998 Mark Mitchell + + * loop.c (maybe_eliminate_biv_1): Avoid signed/unsigned comparison + confusion when setting cc0. + Fri Jul 17 03:26:12 1998 Rihcard Earnshaw (rearnsha@arm.com) * tree.c (valid_machine_attribute): Only create a new type variant if diff --git a/gcc/loop.c b/gcc/loop.c index 0171741e22b7..7e2c4d1d220b 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -6550,7 +6550,42 @@ maybe_eliminate_biv_1 (x, insn, bl, eliminate_p, where) return 1; #ifdef HAVE_cc0 - if (SET_DEST (x) == cc0_rtx && SET_SRC (x) == reg) + /* The idea here is to replace the SET of cc0 by a REG with + a comparison involving related induction variables. + Unfortunately, however, such a replacement does not work + correctly if the REG is being used as signed and the + replacement value is unsigned, or vice versa. For + example, in: + + for (int i = n; i >= 0; --i) + s[i] = 3; + + `s' is an address (an unsigned quantity), while `i' is a + signed quantity. The exit test for the loop might look + something like: + + (SET cc0 i) + (JUMP (SET (PC) (IF_THEN_ELSE (LT (CC0) (CONST_INT 0)) + (LABEL_REF L) (PC)))) + + If we replace the SET of cc0 with a comparison of the + induction variable for `s + i' and the original value of `s', + however, we should be change the comparison in the + IF_THEN_ELSE to be unsigned. Otherwise, an array the spans + the boundary between "negative" and "positive" addresses will + confuse us. + + There are related problems with overflow. If an induction + variable "wraps around" but the original value doest not, we + can get confused when doing the comparison. + + Pointers can't wrap around, or overflow, in a conformant + program. Therefore, it's safe to do these optimizations if + both the original REG and the values in the replacement are + pointers. For now, though, we just disable these + optimizations. */ + + if (0 && SET_DEST (x) == cc0_rtx && SET_SRC (x) == reg) { /* Can replace with any giv that was reduced and that has (MULT_VAL != 0) and (ADD_VAL == 0). diff --git a/gcc/testsuite/gcc.c-torture/execute/loop-2g.c b/gcc/testsuite/gcc.c-torture/execute/loop-2g.c new file mode 100644 index 000000000000..8792dbf586b6 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/loop-2g.c @@ -0,0 +1,63 @@ +#include + +#ifdef __unix__ /* ??? Is that good enough? */ +#include +#include +#include +#include +#ifndef MAP_ANON +#ifdef MAP_ANONYMOUS +#define MAP_ANON MAP_ANONYMOUS +#else +#define MAP_ANON MAP_FILE +#endif +#endif +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif +#ifndef MAP_FIXED +#define MAP_FIXED 0 +#endif +#endif + +#define MAP_START (void *)0x7fff8000 +#define MAP_LEN 0x10000 + +#define OFFSET (MAP_LEN/2 - 2 * sizeof (char)); + +f (int s, char *p) +{ + int i; + for (i = s; &p[i] < &p[40] && i >= 0; i++) + { + p[i] = -2; + } +} + +main () +{ +#ifdef MAP_ANON + char *p; + int dev_zero; + + dev_zero = open ("/dev/zero", O_RDONLY); + /* -1 is OK when we have MAP_ANON; else mmap will flag an error. */ + if (INT_MAX != 0x7fffffffL || sizeof (char *) != sizeof (int)) + exit (0); + p = mmap (MAP_START, MAP_LEN, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_FIXED|MAP_PRIVATE, dev_zero, 0); + if (p != (char *)-1) + { + p += OFFSET; + p[39] = 0; + f (0, p); + if (p[39] != (char)-2) + abort (); + p[39] = 0; + f (-1, p); + if (p[39] != 0) + abort (); + } +#endif + exit (0); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/loop-2g.x b/gcc/testsuite/gcc.c-torture/execute/loop-2g.x new file mode 100644 index 000000000000..e68b8fbb8d29 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/loop-2g.x @@ -0,0 +1,9 @@ +# This doesn't work on m68k-motorola-sysv +# It also doesn't work on m88k-motorola-sysv3 + +global target_triplet +if { [istarget "m68k-motorola-sysv"] || [istarget "m88k-motorola-sysv3"] } { + set torture_compile_xfail "$target_triplet" +} + +return 0