rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.37k stars 12.59k forks source link

Reordered LLVM-IR bbs causing `FileCheck` failures on `aarch64-unknown-none` #127395

Open pvdrz opened 3 months ago

pvdrz commented 3 months ago

This issue came to my attention as it happens on a custom target that we use on ferrocene to test aarch64-unknown-none. However, I was able to reproduce it here as well (on commit 9a21ac8e7ef) and it might cause some errors in the future

The FileCheck test on tests/codegen/vec_pop_push_noop.rs will fail if the basic blocks of the LLVM-IR for the noop function are reordered in such a way that the returning block is not at the end.

This is the IR on x86_64-unknown-linux-gnu (which passes the test):

; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read, inaccessiblemem: write) uwtable
define void @noop(ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %v) unnamed_addr #2 personality ptr @rust_eh_personality {
start:
  %0 = getelementptr inbounds i8, ptr %v, i64 16
  %_4 = load i64, ptr %0, align 8, !noundef !3
  %1 = icmp eq i64 %_4, 0
  br i1 %1, label %bb1, label %"_ZN5alloc3vec16Vec$LT$T$C$A$GT$4push17h6b95231b811ede1dE.exit"

"_ZN5alloc3vec16Vec$LT$T$C$A$GT$4push17h6b95231b811ede1dE.exit": ; preds = %start
  %2 = add i64 %_4, -1
  %_7 = load i64, ptr %v, align 8, !noundef !3
  %_5 = icmp ult i64 %2, %_7
  tail call void @llvm.assume(i1 %_5)
  br label %bb1

bb1:                                              ; preds = %start, %"_ZN5alloc3vec16Vec$LT$T$C$A$GT$4push17h6b95231b811ede1dE.exit"
  ret void
}

And this is the IR on aarch64-unknown-none

; Function Attrs: mustprogress nofree norecurse noredzone nosync nounwind willreturn memory(argmem: read, inaccessiblemem: write)
define dso_local void @noop(ptr noalias nocapture noundef readonly align 8 dereferenceable(24) %v) unnamed_addr #3 {
start:
  %0 = getelementptr inbounds i8, ptr %v, i64 16
  %_2.i = load i64, ptr %0, align 8, !alias.scope !19, !noundef !1
  %.not = icmp eq i64 %_2.i, 0
  br i1 %.not, label %bb3, label %bb7

bb3:                                              ; preds = %start, %bb7
  ret void

bb7:                                              ; preds = %start
  %1 = add i64 %_2.i, -1
  %2 = load i64, ptr %v, align 8, !noundef !1
  %cond.i = icmp ult i64 %1, %2
  tail call void @llvm.assume(i1 %cond.i)
  br label %bb3
}

This is the config.toml I used:

[llvm]
download-ci-llvm = false
assertions = true
static-libstdcpp = true

[build]
host = ["x86_64-unknown-linux-gnu"]
target = ["aarch64-unknown-none"]
docs = false
extended = true
tools = [
   "cargo",
   "clippy",
   "rustdoc",
   "rustfmt",
   "rust-analyzer",
   "rust-analyzer-proc-macro-srv",
   "analysis",
   "src",
   "rust-demangler",  ]
sanitizers = true
cargo-native-static = true
metrics = false

[rust]
debug-assertions = true
channel = "dev"
lld = false
remap-debuginfo = true

[dist]

I had to update the vec_pop_push_noop.rs test so it uses alloc instead of std:

//@ compile-flags: -O
#![no_std]
#![crate_type = "lib"]
extern crate alloc;
#[no_mangle]
// CHECK-LABEL: @noop(
pub fn noop(v: &mut alloc::vec::Vec<u8>) {
    // CHECK-NOT: grow_one
    // CHECK-NOT: call
    // CHECK: tail call void @llvm.assume
    // CHECK-NOT: grow_one
    // CHECK-NOT: call
    // CHECK: ret
    if let Some(x) = v.pop() {
        v.push(x)
    }
}

#[no_mangle]
// CHECK-LABEL: @push_byte(
pub fn push_byte(v: &mut alloc::vec::Vec<u8>) {
    // CHECK: call {{.*}}grow_one
    v.push(3);
}

And finally run:

$ ./x.py test tests/codegen/vec_pop_push_noop.rs

This is the error:

./tests/codegen/vec_pop_push_noop.rs:13:12: error: CHECK: expected string not found in input
 // CHECK: ret
           ^
./vec_pop_push_noop.ll:270:29: note: scanning from here
 tail call void @llvm.assume(i1 %cond.i)
                            ^
./vec_pop_push_noop.ll:274:21: note: possible intended match here
; Function Attrs: noredzone nounwind
                    ^

Input file: ./vec_pop_push_noop.ll
Check file: ./tests/codegen/vec_pop_push_noop.rs

-dump-input=help explains the following input dump.

Input was: ...
veera-sivarajan commented 3 months ago

@rustbot label -needs-triage +A-LLVM +T-compiler +A-testsuite