[LLVMbugs] [Bug 21099] New: incorrect X86 code gen for 64-bit atomic add with literal operand 0xffffffff80000000ULL

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Tue Sep 30 12:43:35 PDT 2014


http://llvm.org/bugs/show_bug.cgi?id=21099

            Bug ID: 21099
           Summary: incorrect X86 code gen for 64-bit atomic add with
                    literal operand 0xffffffff80000000ULL
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Windows NT
            Status: NEW
          Severity: normal
          Priority: P
         Component: Backend: X86
          Assignee: unassignedbugs at nondot.org
          Reporter: warren_ristow at playstation.sony.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

The following test-case, when compiled at -O2 (for x86_64 target):

// ===========================================================
long long atomicAdd64(long long *p) {
  return __sync_fetch_and_add(p, 0xffffffff80000000ULL);
}
void foo(long long *p) { atomicAdd64(p); }
// ===========================================================

produces incorrect assembly code.  The call to 'atomicAdd64()' in 'foo()' has
been inlined, but the code to implement the fetch-and-add isn't there.  Here is
a disassembly for a compilation with r218661, done with
'-O2 -target x86_64-pc-linux-gnu':

    test.o: file format ELF64-x86-64

    Disassembly of section .text:
    _Z11atomicAdd64Px:
           0:       48 c7 c0 00 00 00 80            movq    $-2147483648, %rax
           7:       f0                              lock
           8:       48 0f c1 07                     xaddq   %rax, (%rdi)
           c:       c3                              retq
           d:       0f 1f 00                        nopl    (%rax)

    _Z3fooPx:
          10:       c3                              retq

Two relevant points are:

  1.  The behavior changed with r216768.  Prior to that revision, there was a
      compiler crash with the command:

        clang++ -c -O2 -target x86_64-pc-linux-gnu test.cpp

      If an assembly file is produced (when using a compiler prior to r216768)
      there isn't a compiler crash, and the underlying issue is clearer when
      attempting to assemble it.  Specifically, an illegal literal value is in
      the generated assembly code.  Using r216767:

        $ clang++ -S -O2 -target x86_64-pc-linux-gnu test.cpp
        $ clang++ -c -target x86_64-pc-linux-gnu test.s
        test.s:24:7: error: invalid operand for instruction
                subq    $2147483648, (%rdi)     # imm = 0x80000000
                        ^~~~~~~~~~~
        $

      That is, prior to r216768, an illegal assembly instruction was generated,
      causing a build-time failure.  Beginning with r216768, that illegal
      instruction isn't generated, but rather than being replaced with
      corrected instructions, no instruction is generated, allowing the build
      to complete, but causing a potential run-time failure.

  2.  Using an assertion-checking build of the compiler, an assert fires.  The
      failing check changes with r216768, but there is a failure both before
      and after.  Prior to r216768, the assertion-failure was:

        Assertion failed: isReg() && "This is not a register operand!",
                file ..../llvm/include/llvm/MC/MCInst.h, line 64

      Beginning with r216768, the failing check is:

        Assertion failed: Opc != 0 && "Invalid arith lock transform!",
                file ..../llvm/lib/Target/X86/X86ISelDAGToDAG.cpp, line 1823

The key issue seems to be that if the immediate value is representable as a
signed 32-bit number, the Addition for '__sync_fetch_and_add()' is changed to a
Subtraction, and the immediate value is negated.  In this case, the immediate
value is -2147483648, but since the negation of it isn't representable as a
32-bit signed number, that transformation can't be done.  Also, some other
optimization/transformation appears relevant, in that (for the example given)
the code for 'atomicAdd64()' is correct, but the code for 'foo()' (the caller
of 'atomicAdd64()') shows the problem (has the illegal immediate value prior to
r216768, and the missing instructions beginning with r216768).

-- 
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/20140930/ba7cbf9f/attachment.html>


More information about the llvm-bugs mailing list