Unexplained absolute addressing mode generated on amd64/FreeBSD. Bug?

Good evening!

I'm experiencing weird code generation on amd64 FreeBSD with the
system's clang 10.0.1. specifically, an absolute addressing mode is
unexpectedly chosen for ucomisd with a memory constant where I would
normally expect a rip-relative addressing mode. The behaviour has
proven to be hard to reproduce. Any attempt to simplify the code leads
to perfectly fine code. To reproduce, download my project:


and compile dobutsu.c with -O3 on amd64/FreeBSD (Linux should work,
too). The output has a bunch of instructions like this:

    ucomisd .LCPI0_0, %xmm1

with an absolute addressing mode where I would expect a relative
addressing mode like

    ucomisd .LCPI0_0(%rip), %xmm1

I wonder what the reason for this could be. I can reproduce this
error with clang 11.0.1 from FreeBSD but haven't been able to test
12.0. Will continue to try and reduce the example.

Robert Clausecker

With some help from the IRC, I managed to use creduce to cut down the
test case. The result is this:

    double a;
    c() {
        while (b)
            if (a)

This produces code like this (slightly cleaned up):

            .quad 0
    b: .long 0
    c: pushq %rbp
            movq %rsp, %rbp
            movl b(%rip), %eax
            testl %eax, %eax
            je .LBB0_5
            movsd a(%rip), %xmm0
            ucomisd .LCPI0_0, %xmm0 ; ???
            jne .LBB0_4
            jnp .LBB0_2
            xorl %eax, %eax
            callq d
            jmp .LBB0_1
            popq %rbp

Why is an absolute addressing mode instead of a rip-relative addressing
mode chosen for the memory operand to ucomisd? And why is zero loaded
from memory at all? I might not be an expert, but

            xorsd %xmm0, %xmm0
            ucomisd a(%rip), %xmm0

looks a bit better than the movsd/ucomisd pair clang comes up with.

Robert Clausecker