Messages in this thread | | | Date | Wed, 10 Apr 1996 10:49:59 -0700 | From | (Tom May) | Subject | gcc 2.7.2 common subexpression bug with possible kernel implications |
| |
Hi,
I just sent a bug report and patch to bug-gcc concerning a problem in gcc 2.7.2 common subexpression elimination that has possible implications in the linux kernel. Until it is fixed, I would recommend compiling with the "-fno-cse-skip-blocks" switch. This bug may exist in earlier compilers also, but I don't know for sure.
Here's the explanation and example I submitted, which was originally from the linux kernel but has been pared down extremely to make the bug easier to find. I found this bug while compiling a version of the kernel that I had been tweaking, so I don't know if it breaks the real kernel, but the potential is certainly there.
Explanation: The common subexpression elimination code is currently ignoring clobbers of "memory" in __asm__ constructs which occur in skipped blocks (e.g., inside an `if'). I'm using gcc 2.7.2 configured with "./configure --prefix=/usr i486-linux", for this example, but this is an architecture-independent problem.
Example: The test for `p->len == 0' is being deleted by cse because of the `p->len = 0' a few lines earlier. This is incorrect, because __memcpy() may clobber that memory.
extern inline void * __memcpy(void * to, const void * from, unsigned n) { __asm__ __volatile__( "cld\n\t" "rep ; movsl\n\t" "testb $2,%b1\n\t" "je 1f\n\t" "movsw\n" "1:\ttestb $1,%b1\n\t" "je 2f\n\t" "movsb\n" "2:" : :"c" (n/4), "q" (n),"D" ((long) to),"S" ((long) from) : "cx","di","si","memory"); return (to); }
struct thing { int len; int data; };
void spud (struct thing *in, int copy) { unsigned char buf[sizeof(struct thing)+40]; struct thing * p = (struct thing*)buf;
p->len = 0; if (copy) __memcpy (buf, in, sizeof(struct thing) + in->len); if (p->len == 0) { p->len = 1; } }
That's all for now. Tom.
| |