+Sat Jul 18 15:20:19 1998 Mark Mitchell <mark@markmitchell.com>
+
+ * 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
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).
--- /dev/null
+#include <limits.h>
+
+#ifdef __unix__ /* ??? Is that good enough? */
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#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);
+}