[Vm-dev] clang and bytecodePrimMultiply

Eliot Miranda eliot.miranda at gmail.com
Tue Nov 24 19:44:49 UTC 2015


Hi All,

    I'm trying to use clang in Xcode on Mac OS X to compile a new 32-bit
VM.  One of my installations is Mavericks 10.9 with Xcode 6.2 and clang
6.0.  The other is 10.10.5 with Xcode 7.1 and clang 7.0.  Both seem to have
problems with the integer side of bytecodePrimMultiply, the interpreter's
multiplication routine:

        CASE(184)
            /* bytecodePrimMultiply */
            {
                sqInt arg;
                sqInt rcvr;
                sqInt result;
                char *sp;

                VM_LABEL(bytecodePrimMultiply);
                rcvr = longAtPointer(localSP + (1 * BytesPerOop));
                arg = longAtPointer(localSP + (0 * BytesPerOop));
                if (((rcvr & arg) & 1) != 0) { // both SmallIntegers?
                    rcvr = (rcvr >> 1); // convert from SmallInteger to
value
                    arg = (arg >> 1);
                    result = rcvr * arg; // multiply
                    if ((arg == 0)
                     || (((result / arg) == rcvr) // check for overflow
                     && ((((sqInt)(result ^ (result << 1)))) >= 0))) { //
check for SmallInteger overflow
                        /* begin internalPop:thenPush: */
                        longAtPointerput((localSP += (2 - 1) *
BytesPerOop), ((result << 1) | 1));
                        /* begin fetchNextBytecode */
                        currentBytecode = byteAtPointer(++localIP);

                        goto l58;
                    }
                }
                else {

clang 6 inserts a spurious instruction at 0x36799:

0x36784: 89 ca movl %ecx, %edx // both SmallIntegers?
0x36786: 83 e2 01 andl $0x1, %edx
0x36789: 85 d0 testl %eax, %edx
0x3678b: 74 6b je 0x367f8
0x3678d: d1 f9 sarl %ecx // convert from SmallInteger to value
0x3678f: d1 f8 sarl %eax
0x36791: 0f af c8 imull %eax, %ecx // do the multiply
0x36794: 8d 14 09 leal (%ecx,%ecx), %edx
0x36797: 85 c0 testl %eax, %eax
0x36799: 89 f7 movl %esi, %edi // AFAICS, totally spurious
0x3679b: 74 08 je 0x367a5
0x3679d: 31 d1 xorl %edx, %ecx // check for SmallInteger overflow
0x3679f: 0f 88 96 01 00 00 js 0x3693b
0x367a5: 83 ca 01 orl $0x1, %edx

clang 7 does better:
0x36741: 89 ca movl   %ecx, %edx // both SmallIntegers?
0x36743: 83 e2 01 andl   $0x1, %edx
0x36746: 85 d0 testl  %eax, %edx
0x36748: 74 67 je     0x367b1
0x3674a: d1 f9 sarl   %ecx // convert from SmallInteger to value
0x3674c: d1 f8 sarl   %eax
0x3674e: 0f af c8 imull  %eax, %ecx // do the multiply
0x36751: 8d 14 09 leal   (%ecx,%ecx), %edx
0x36754: 85 c0 testl  %eax, %eax
0x36756: 74 08 je     0x36760
0x36758: 31 d1 xorl   %edx, %ecx // check for SmallInteger overflow
0x3675a: 0f 88 a9 01 00 00 js     0x36909
0x36760: 83 ca 01 orl    $0x1, %edx


What I don't understand is how, given

                typedef long sqInt;
                sqInt arg;
                sqInt rcvr;
                sqInt result;
...
                    result = rcvr * arg; // multiply

clang reasons it doesn't need to evaluate

                     || (((result / arg) == rcvr) // check for overflow

Given that arg and receiver can both have values > 64k, the result can of
course overflow and there's no guarantee that because result = rcvr * arg,
that (result / arg) == rcvr.

Am I missing something?  Are there flags I should be using?  This looks
like a pretty basic issue.

_,,,^..^,,,_
best, Eliot
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/vm-dev/attachments/20151124/8819448c/attachment-0001.htm


More information about the Vm-dev mailing list