Code generation change between llvm 11 and 12, amd64

I’m working on updating Valgrind for FreeBSD 13.1 (I’m the maintainer, and FreeBSD 13.1 was officially released today).

One of the problems that I see is with the testcase none/tests/amd64/amd64locked

Here’s a link to the source

https://sourceware.org/git/?p=valgrind.git;a=blob;f=none/tests/amd64/amd64locked.c;h=baf9bbe1eca91ac672e4373d8f58a476cf4de9d5;hb=HEAD

The problem is not related to Valgrind. If I run the executable alone it fails

$ ./amd64locked
amd64locked: FAIL: CRCs actual 0xA248D739 expected 0xDF0656F1
amd64locked: set #define VERBOSE 1 to diagnose

This is on FreeBSD 13.1 RC6 amd64 running on VirtualBox, compiler version

FreeBSD clang version 13.0.0 (git@github.com:llvm/llvm-project.git llvmorg-13.0.0-0-gd7b669b3a303)

I’m not familiar with the code. It’s a long test for all amd64 instructions with a lock prefix performing CRC calculations. Compiled without optimization it passes

The source contains this comment

// So there should be 118 lock-prefixed instructions in the
// disassembly of this compilation unit.
// confirm with
// objdump -d ./amd64locked | grep lock | grep -v do_lock | grep -v elf64 | wc

This also gives the wrong output.

$ objdump -d ./amd64locked | grep lock | grep -v do_lock | grep -v elf64 | wc
136 1193 7376

I’ll see if I can reproduce the failure on Linux (Fedora 34). I’ll also look at the assembler to see if I can at least get an idea of what has changed. I can also probably try a more recent llvm on FreeBSD.

UPDATE:
I need to redo my tests on Linux to make sure I’m compiling with -g -O
Higher optimization seems more problematic.

The code goes generate quite a few warnings with -Weverything: inplicit int and sign conversions, superfluous semicolons, and shortening.

Can anyone help with this?

You may need to narrow it down to a function (with a clang command line) which has unexpected code generation, then someone working on the x86 backend may help. Setting up an environment to verify an issue will scare off many folks who may be able to help.

I’ve started looking at the disassembly. I’ll also look at the debug output. They are, however, large and huge respectively. I might also give git bisect a go.

There is no environment to set up. Repeating what I said

The problem is not related to Valgrind. If I run the executable alone it fails.

To reproduce, download the source file from the link.
Compile it with clang -g -O
And run it.

If it says FAILED then the problem has been reproduced.

The problem seems to be in
void do_bt_G_E_tests ( void )

If I add a printf to try to observe carrydep the problem goes away.

Looking at the disassmbler, the first thing that I see is that clang13 has inlined myrandom(). If I add __attribute__((noinline)) to that then the problem goes away.

Still, this looks like a clang code gen optimization bug to me.