Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

8-bit and 16-bit atomic operations return wrongly extended results #27598

Closed Quuxplusone closed 8 years ago

Quuxplusone commented 8 years ago
Bugzilla Link PR27599
Status RESOLVED FIXED
Importance P normal
Reported by Marcin Kościelnicki (koriakin@0x04.net)
Reported on 2016-05-02 04:33:36 -0700
Last modified on 2016-05-10 15:38:04 -0700
Version trunk
Hardware Other Linux
CC llvm-bugs@lists.llvm.org
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
The following function:

char f(char *x, char y, char z) {
        return __sync_val_compare_and_swap(x, y, z);
}

compiles to that:

define zeroext i8 @f(i8* nocapture, i8 zeroext, i8 zeroext) #0 {
  %4 = cmpxchg i8* %0, i8 %1, i8 %2 seq_cst seq_cst
  %5 = extractvalue { i8, i1 } %4, 0
  ret i8 %5
}

which compiles to that:

f:                                      # @f
# BB#0:
        stmg    %r13, %r15, 104(%r15)
        risbg   %r1, %r2, 0, 189, 0
        sll     %r2, 3
        lcr     %r5, %r2
        l       %r0, 0(%r1)
.LBB0_1:                                # =>This Inner Loop Header: Depth=1
        rll     %r14, %r0, 8(%r2)
        risbg   %r3, %r14, 32, 55, 0
        crjlh   %r14, %r3, .LBB0_3
# BB#2:                                 #   in Loop: Header=BB0_1 Depth=1
        risbg   %r4, %r14, 32, 55, 0
        rll     %r13, %r4, -8(%r5)
        cs      %r0, %r13, 0(%r1)
        jl      .LBB0_1
.LBB0_3:
        llgfr   %r2, %r14
        lmg     %r13, %r15, 104(%r15)
        br      %r14

The function ends with a llgfr, zero extending i32 to i64 - however, the high
24 bits of %r14 contain junk at this point, so the result will be wrong.  This
breaks ASan tests when the ASan runtime is compiled by clang.

It seems CodeGen assumes that sub-word atomic operations return zero-extended
(or sign-extended if TLI says so) results, and SystemZ doesn't deliver.
Quuxplusone commented 8 years ago

Fixed by rL269075