[llvm-bugs] [Bug 27730] New: left shift is broken for negative <16 x i16> on avx2

via llvm-bugs llvm-bugs at lists.llvm.org
Thu May 12 20:36:23 PDT 2016


https://llvm.org/bugs/show_bug.cgi?id=27730

            Bug ID: 27730
           Summary: left shift is broken for negative <16 x i16> on avx2
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: Backend: X86
          Assignee: unassignedbugs at nondot.org
          Reporter: andrew.b.adams at gmail.com
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

I think there's a bug in lowering left-shifts of wider-than-native 16-bit
signed integer vectors on haswell. It's computing incorrect values. 

With the following .ll:

define void @fn(<16 x i16> * %a_ptr, <16 x i16> * %b_ptr, <16 x i16> * %c_ptr)
{
       %a = load <16 x i16>, <16 x i16> * %a_ptr
       %b = load <16 x i16>, <16 x i16> * %b_ptr
       %result = shl <16 x i16> %a, %b
       store <16 x i16> %result, <16 x i16> * %c_ptr
       ret void
}

driven by the following test code:

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

extern "C" void fn(int16_t *a, int16_t *b, int16_t *c);

int main(int argc, char **argv) {
    int16_t *a = (int16_t *)aligned_alloc(32, 32);
    int16_t *b = (int16_t *)aligned_alloc(32, 32);
    int16_t *c = (int16_t *)aligned_alloc(32, 32);

    for (int i = 0; i < 16; i++) {
        a[i] = -3;
        b[i] = i/2;
    }

    fn(a, b, c);

    for (int i = 0; i < 16; i++) {
        printf("%d vs %d\n", a[i] * (1 << b[i]), c[i]);
    }

    return 0;
}

Note that there's no nuw or nsw tag on my shl, and I'm shifting a small value
by a small amount, so there's no (signed) overflow happening. The language
reference seems to indicate that this is well-defined, and should be equivalent
to the shift-and-multiply in the driver.

We get a disagreement between the driver and the vector code:

$ llc vector_shl.ll -mcpu=haswell -o vector_shl.s
$ clang++ driver.cpp vector_shl.s
$ ./a.out
-3 vs -3
-3 vs -3
-6 vs -5
-6 vs -5
-12 vs -9
-12 vs -9
-24 vs -17
-24 vs -17
-48 vs -33
-48 vs -33
-96 vs -65
-96 vs -65
-192 vs -129
-192 vs -129
-384 vs -257
-384 vs -257

Sandybridge works fine:

$ llc vector_shl.ll -mcpu=sandybridge -o vector_shl.s
$ clang++ driver.cpp vector_shl.s
$ ./a.out
-3 vs -3
-3 vs -3
-6 vs -6
-6 vs -6
-12 vs -12
-12 vs -12
-24 vs -24
-24 vs -24
-48 vs -48
-48 vs -48
-96 vs -96
-96 vs -96
-192 vs -192
-192 vs -192
-384 vs -384
-384 vs -384

native <8 x i16> vectors also seem to work fine for either target.

trunk, 3.8, and 3.7 all give the same behavior, so either this is an old bug,
or I'm misunderstanding what counts as UB here.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160513/73717f51/attachment.html>


More information about the llvm-bugs mailing list