rust-lang / rust

Empowering everyone to build reliable and efficient software.

Home Page:https://www.rust-lang.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

fetch_max broken for atomici8 and atomici16 on some targets.

plugwash opened this issue · comments

The rust atomic crate was recently uploaded to Debian, unfortunately on a number of Debian architectures it's tests failed.

---- tests::atomic_i16 stdout ----
thread 'tests::atomic_i16' panicked at 'assertion failed: `(left == right)`
  left: `-25`,
 right: `30`', src/lib.rs:448:9
---- tests::atomic_i8 stdout ----
thread 'tests::atomic_i8' panicked at 'assertion failed: `(left == right)`
  left: `-25`,
 right: `30`', src/lib.rs:428:9

The debian architectures where it failed and the corresponding rust architectures are listed below.

armel -> armv5te-unknown-linux-gnueabi
mips64el -> mips64el-unknown-linux-gnuabi64
mipsel -> mipsel-unknown-linux-gnu
powerpc -> powerpc-unknown-linux-gnu

My guess is that this is a bug in fallback code used when the architecture does not natively support 8 and 16 bit atomics.

I produced the following testcase to confirm this was not a problem in the atomic crate, but instead an issue in either the compiler or the standard library. I tested this on Debian armel.

use std::sync::atomic::Ordering::SeqCst;
use std::sync::atomic::AtomicI8;
use std::sync::atomic::AtomicI16;
use std::sync::atomic::AtomicI32;
fn main() {
    let a = AtomicI8::new(30);
    println!("{}",a.fetch_max(-25,SeqCst));
    println!("{}",a.load(SeqCst));
    let a = AtomicI16::new(30);
    println!("{}",a.fetch_max(-25,SeqCst));
    println!("{}",a.load(SeqCst));
    let a = AtomicI32::new(30);
    println!("{}",a.fetch_max(-25,SeqCst));
    println!("{}",a.load(SeqCst));
}

I expected this to print 30 six times, but the second and fourth lines of the output are instead -25, this shows fetch_max is not being implemented correctly for AtomicI8 and AtomicI16 (but is being implemented correctly for AtomicI32).

I've only tested this with Debian's rustc so far, I may try to test with upstream rustc but this is complicated by the fact that I don't think upstream offers binaries for armv5te-unknown-linux-gnueabi

Meta

rustc --version --verbose:

rustc 1.59.0
binary: rustc
commit-hash: unknown
commit-date: unknown
host: armv5te-unknown-linux-gnueabi
release: 1.59.0
LLVM version: 13.0.1

I've only tested this with Debian's rustc so far, I may try to test with upstream rustc but this is complicated by the fact that I don't think upstream offers binaries for armv5te-unknown-linux-gnueabi

Correct, unfortunately. This will likely require building from source.
Please feel free to open any issues you run into if you do that.
Also, we currently use a version of LLVM 15, recently upgraded from LLVM 14. It would be useful to know if using the old LLVM is what decides the matter.

Unfortunately, LLVM has reduced their support for atomics on some platforms, and Rust attempts to avoid exposing anything but hardware atomics, so there might even be flat-out regressions on some of these: #99668

Also:

armv5te-unknown-linux-gnueabi

This is in fact a tier 2 platform, apparently, so we do distribute std for this target and you can cross-compile for it.

And 2 more LLVM bugs in the MIPS and PowerPC backends:

Hi @plugwash @Amanieu,

I have tested the testcase in my lab, and the results were as expected.

The target environment is mips64el, Debian GNU/Linux 11, gcc version 12.2.0, glibc 2.36-9, kernel version 5.10.0-22-loongson-3.

$ ./test2
30
30
30
30
30
30

And the cross compile environment is x86:

$ ~/rust-test/bin/rustc --version --verbose
rustc 1.76.0-dev
binary: rustc
commit-hash: unknown
commit-date: unknown
host: x86_64-unknown-linux-gnu
release: 1.76.0-dev
LLVM version: 17.0.5

$ ~/rust-test/bin/rustc --target mips64el-unknown-linux-gnuabi64 -Clinker=mips64el-linux-gnuabi64-gcc -Ctarget-feature=+crt-static -Clink-arg=-static -o test2 ./src/main.rs

LLVM seems to still generate incorrect assembly: https://godbolt.org/z/z9TxWTrzq

I'm not sure why it's working for you.

I have tried to reproduce the issue for mipsel and it is working fine. Can you confirm that you are still seeing the issue?

The bug has been fixed in upstream LLVM (llvm/llvm-project#77072) and will be back-ported to the 18.x branch used by rustc.

I suggest we remove the O-MIPS label due to the bug being fixed in upstream LLVM for MIPS targets.

I've removed the MIPS and PowerPC label since those are now fixed.

*EDIT: MIPS is fixed, not ARM.

I had the MIPS fix merged into the 18 branch and will be out for 18.1.3.

llvm/llvm-project#86424

LLVM 18.1.3 has been released.

@rustbot label llvm-fixed-upstream

Hmm, I can confirm that the issue has been fixed in af25253. This is LLVM 18.1.2. However, it's broken in 18.1.3.

LLVM seems to still generate incorrect assembly: https://godbolt.org/z/z9TxWTrzq

I'm not sure why it's working for you.

I don't know anything with MIPS, but judging from the output, it seems that 18.1.2 has resolved these two issues. I will try to find the relevant commit.

Yes, MIPS seems to be fixed. It's just ARM that still has the bug (llvm/llvm-project#61880).

Yes, MIPS seems to be fixed. It's just ARM that still has the bug (llvm/llvm-project#61880).

Thanks. We still need to fix the ARM issue.
@rustbot label -llvm-fixed-upstream

The MIPS patch set was reverted for the 18 branch. But a proper fixed patch set will be hashed out for the 19 release.