Messages in this thread | | | Subject | Re: Recent change in tcp_output.c is surely wrong | Date | Tue, 18 Jan 2000 11:38:14 +0100 (MET) | From | (Rogier Wolff) |
| |
Jamie Lokier wrote: > Rogier Wolff wrote: > > On the other hand, having thousands "silent departures from ANSI-C" > > scattered through the kernel is not a good idea. I'm fine with having > > a few __asm__ thingies that generate errors while compiling/linking. > > > > Someone is eventually going to have to port Linux to an architecture > > that doesn't have a gcc port yet. > > It breaks with GCC too. How obvious do I have to be? > > #include <stdio.h> > int main () > { > unsigned short a = 0xffff; > a = (a << 1) >> 1; > printf ("a = 0x%x\n", (unsigned) a); > return 0; > } > > $ gcc -o test test.c > $ ./test > a = 0xffff
More reason, that IF you find the performance impact high enough, you should do it with a macro, that can be changed to adopt to the currrent status of compiler, length of types etc etc.
> > --> high bit /not/ cleared > > > Oh, by the way, ANSI defines the behaviour as undefined, as a compiler > > is allowed to recognize that (var <<1) >> 1 evaluates to "var" if done > > with arbitrary precision. > > No. For any unsigned type as wide or wider than `unsigned int', that > will clear the top bits. For narrower unsigned types it won't. For > signed types it is implementation defined.
Hmm. I'm not too familiar with the exact wording of ANSI. However, they usually take the road where "more accuracy in intermediates is allowed", as that can normally only reduce the amount of trouble that you get into when things near the limit of the size you're using.
> > for example > > > > array [index>>4].firstbyte = 0; > > > > could evaluate (the element size of array happens to be 16 bytes!) > > > > * (char *)array + (index & ~0xf) = 0; > > > > See, the compiler recognized that two shifts over the same width are > > the same. > > Your example is wrong. You've shown `(a >> 4) << 4', which is obviously > equal to `a & ~0xf' for any type :-)
Is a compiler allowed to optimize
a + 4 - 4
into "a"?
There are "opposites" that can be taken together. So in principle:
(a >> 4) << 4 == a
except that a few bits fall off at the binary point.
Similarly we agree that
(a << 4) >> 4 == a
except that a few bits fall off at the high end. However, that's (as you've demonstrated) dependent on the size of the intermediates involved.
If you're right that a compiler may not extend the size of the intermediates beyond the size of an unsiged int, the Alpha compiler is in trouble, as it has to explicitly cater for this. Ints on Alpha are 32 bits, but registers are 64 bits, so it will have to explicitly clip the intermediate on:
(a << 4) >> 4
Usually, ANSI will take the road where the compiler writer is allowed to optimize for the common case: More accuracy usually doesn't matter.
Roger.
-- ** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2137555 ** *-- BitWizard writes Linux device drivers for any device you may have! --* "I didn't say it was your fault. I said I was going to blame it on you."
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |