[Vm-dev] [commit] r2463 - CogVM source as per VMMaker.oscog-eem.105. Fix signed32BitValueOf for most neg-

Eliot Miranda eliot.miranda at gmail.com
Thu Jul 21 17:35:00 UTC 2011


On Thu, Jul 21, 2011 at 4:30 AM, David T. Lewis <lewis at mail.msen.com> wrote:

>
> On Thu, Jul 21, 2011 at 07:08:18AM -0400, David T. Lewis wrote:
> >
> > Commit message blocked due to size, forwarding trimmed version:
> >
> > Author: eliot
> > Date: 2011-07-18 17:35:51 -0700 (Mon, 18 Jul 2011)
> > New Revision: 2463
>
> <snip>
>
> > Log:
> > CogVM source as per VMMaker.oscog-eem.105.  Fix signed32BitValueOf for
> most neg-
> > ative value C compiler mis-optimization.  Speed up primitiveFail using !
> trick.
> > Add multi-threaded sources to tree (won't build yet due to issue in
> ia32abicc.c)
> > Upgrade nscogsrc/plugins to official versions.
>
> Hi Eliot,
>
> Can you say what the issue was with signed32BitValueOf? I can
> see the changes in InterpreterPrimitives>>signed32BitValueOf:
> but I'm not clear on whether this is something that affects
> Alien, or if it is something that has been causing problems
> more generally but went unnoticed. Also, I'd like to document
> this with a unit test, so if you can suggest a code snippet
> that would be great.
>

The unit test is in the lien tests and is the attempt to assign max neg int
(-2^31) through signedLongAt:put:.  The problem is due to a pervasive C
compiler bug with optimization.  Recall that max neg int is exceptional in
that it is the only value in a 2's complement representation that can't be
negated since max neg int = -max pos int - 1.  Here's the bug, and it
occurred in signed64BitValueOf: and signedMachineIntegerValueOf: as well; I
slipped in not fixing signed32BitValueOf:

<var: #value type: #int>
...
 (negative
 and: [self
cCode: [value - 1 > 0]
inSmalltalk: [value = -16r80000000]]) ifTrue: "Don't fail for -2147483648
/-16r80000000"

Since value is int (32 bits on relevant systems) then if value =
16r80000000, value - 1 will wrap around to 16r7fffffff, bit all other
negative values will remain negative.  Hence value - 1 > 0 /should/ cheaply
identify max neg int.  But both gcc in many versions, and icc, the intel
compiler, under optimization assume that value - 1 > 0 is always false, and
hence cause the primitive to fail for max neg int.

Instead, the solution I've adopted is to use a different sequence using
shifts that is not mis-optimized, at least by gcc and icc:

 (negative and: [0 = (self cCode: [value << 1]
inSmalltalk: [value << 1 bitAnd: (1 << 32) - 1])]) ifTrue:

i.e. 16r8000000 is the only negative value (0 is positive) that when shifted
left within a 32-bit type equals zero since the sign bit is shifted out.

And to those C compilers, grrr.... ;)


> TIA,
> Dave
>
>


-- 
best,
Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20110721/b3c9680c/attachment.htm


More information about the Vm-dev mailing list