[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