Reordered LLVM-IR bbs causing `FileCheck` failures on `aarch64-unknown-none`
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
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: ...
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with tests/codegen/vec_pop_push_noop.rs and reproduce the failure with ./x.py test tests/codegen/vec_pop_push_noop.rs using the reported aarch64-unknown-none setup. Inspect the generated vec_pop_push_noop.ll and the FileCheck directives around noop; done means the test passes despite the reordered LLVM-IR basic blocks.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100