llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

[ARM][BUG] Run bad result for vect_type in arm32be

Open hstk30-hw opened this issue 1 year ago • 2 comments

https://godbolt.org/z/vYKsfos5o

typedef short int SV __attribute__((vector_size(16)));
extern void abort(void);

__attribute__((noinline)) void vec_div(SV *x, SV *y)
{
    *x = *y / ((SV){1, 4, 2, 8, 16, 64, 32, 128});
}

SV s[] = {
    ((SV){73, -9123, 32761, 8191, 16371, 1201, 12701, 9999}), 
    ((SV){9903, -1, -7323, 0, -7, -323, 9124, -9199})
};

int main()
{
    SV sr, sr2;
    int i;

    for (i = 0; i < sizeof(s) / sizeof(s[0]); i++) {
        vec_div(&sr, s + i);
        if (sr[0] != s[i][0] / 1 || sr[3] != s[i][3] / 8)
            abort();
        asm volatile("" : : "r"(&sr) : "memory");
    }
    return 0;
}

The expected sr is

[73, -2280, 16380, 1023, 1023, 18, 396, 78]

the result is

[-2280, 73, 1023, 16380, 18, 1023, 78, 396]

I guess rev instruction is misused.

(The vectorize for big endian mode in llvm use rev to handle byte ordering, and introduces many rev instrution, also some bugs. https://llvm.org/docs/BigEndianNEON.html)

hstk30-hw avatar Jul 05 '24 02:07 hstk30-hw

@llvm/issue-subscribers-backend-arm

Author: None (hstk30-hw)

https://godbolt.org/z/vYKsfos5o
typedef short int SV __attribute__((vector_size(16)));
extern void abort(void);

__attribute__((noinline)) void vec_div(SV *x, SV *y)
{
    *x = *y / ((SV){1, 4, 2, 8, 16, 64, 32, 128});
}

SV s[] = {
    ((SV){73, -9123, 32761, 8191, 16371, 1201, 12701, 9999}), 
    ((SV){9903, -1, -7323, 0, -7, -323, 9124, -9199})
};

int main()
{
    SV sr, sr2;
    int i;

    for (i = 0; i &lt; sizeof(s) / sizeof(s[0]); i++) {
        vec_div(&amp;sr, s + i);
        if (sr[0] != s[i][0] / 1 || sr[3] != s[i][3] / 8)
            abort();
        asm volatile("" : : "r"(&amp;sr) : "memory");
    }
    return 0;
}

The expected sr is

[73, -2280, 16380, 1023, 1023, 18, 396, 78]

the result is

[-2280, 73, 1023, 16380, 18, 1023, 78, 396]

I guess rev instruction is misused.

(The vectorize for big endian mode in llvm use rev to handle byte ordering, and introduces many rev instrution, also some bugs. https://llvm.org/docs/BigEndianNEON.html)

llvmbot avatar Jul 05 '24 02:07 llvmbot

@llvm/issue-subscribers-bug

Author: None (hstk30-hw)

https://godbolt.org/z/vYKsfos5o
typedef short int SV __attribute__((vector_size(16)));
extern void abort(void);

__attribute__((noinline)) void vec_div(SV *x, SV *y)
{
    *x = *y / ((SV){1, 4, 2, 8, 16, 64, 32, 128});
}

SV s[] = {
    ((SV){73, -9123, 32761, 8191, 16371, 1201, 12701, 9999}), 
    ((SV){9903, -1, -7323, 0, -7, -323, 9124, -9199})
};

int main()
{
    SV sr, sr2;
    int i;

    for (i = 0; i &lt; sizeof(s) / sizeof(s[0]); i++) {
        vec_div(&amp;sr, s + i);
        if (sr[0] != s[i][0] / 1 || sr[3] != s[i][3] / 8)
            abort();
        asm volatile("" : : "r"(&amp;sr) : "memory");
    }
    return 0;
}

The expected sr is

[73, -2280, 16380, 1023, 1023, 18, 396, 78]

the result is

[-2280, 73, 1023, 16380, 18, 1023, 78, 396]

I guess rev instruction is misused.

(The vectorize for big endian mode in llvm use rev to handle byte ordering, and introduces many rev instrution, also some bugs. https://llvm.org/docs/BigEndianNEON.html)

llvmbot avatar Jul 05 '24 02:07 llvmbot

Hi - The last vrev64.32 looks suspicious. There is a call to bitcast here: https://github.com/llvm/llvm-project/blob/74984dee51307779a3eab10a8cd6102be37e1081/llvm/lib/Target/ARM/ARMISelLowering.cpp#L14801, that should probably be an nvcast / ARMISD::VECTOR_REG_CAST instead.

davemgreen avatar Jul 05 '24 07:07 davemgreen

Thx bro, the last vrev64.32 should be vrev64.16. I'll fix it.

hstk30-hw avatar Jul 06 '24 01:07 hstk30-hw

Fixed it.

hstk30-hw avatar Jul 08 '24 06:07 hstk30-hw

Hi - The last vrev64.32 looks suspicious. There is a call to bitcast here:

https://github.com/llvm/llvm-project/blob/74984dee51307779a3eab10a8cd6102be37e1081/llvm/lib/Target/ARM/ARMISelLowering.cpp#L14801

, that should probably be an nvcast / ARMISD::VECTOR_REG_CAST instead.

Hi, I have a question. Is there any other BITCAST should be ARMISD::VECTOR_REG_CAST in ARMISelLowering.cpp?

All bitcasts of the vector type need to be converted, is that right?

for example: https://github.com/llvm/llvm-project/blob/74984dee51307779a3eab10a8cd6102be37e1081/llvm/lib/Target/ARM/ARMISelLowering.cpp#L6331

Jolyon0202 avatar Aug 03 '24 10:08 Jolyon0202

There might well be other places where this is wrong for sure. It shouldn't matter in others though. If the element size is there same then there should not be a differences between the two operations IIRC, and if the value is all zeros (as in getZeroVector), then it would still be all-zeroes after a bitcast/VECTOR_REG_CAST.

davemgreen avatar Aug 03 '24 10:08 davemgreen