Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segmentation fault during optimization pass with aarch64 simd #84020

Closed
calebzulawski opened this issue Apr 8, 2021 · 8 comments
Closed

Segmentation fault during optimization pass with aarch64 simd #84020

calebzulawski opened this issue Apr 8, 2021 · 8 comments
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-simd Area: SIMD (Single Instruction Multiple Data) C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ O-AArch64 Armv8-A or later processors in AArch64 mode requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@calebzulawski
Copy link
Member

The following code seg faults during optimization. I've produced it on both macOS and Linux.

Discussions:
https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd/topic/2021-03-29.20Meeting
https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd/topic/Aarch64.20LLVM.20bug
https://rust-lang.zulipchat.com/#narrow/stream/187780-t-compiler.2Fwg-llvm/topic/Debugging.20segfault.20in.20LLVM

Code

#![feature(const_generics, platform_intrinsics, repr_simd)]
#![allow(incomplete_features)]

extern "platform-intrinsic" {
    fn simd_eq<T, U>(a: T, b: T) -> U;
    fn simd_and<T>(a: T, b: T) -> T;
}

#[derive(Copy, Clone)]
#[repr(simd)]
pub struct F<const N: usize>([f32; N]);

impl<const N: usize> F<N> {
    pub fn splat(value: f32) -> Self {
        Self([value; N])
    }

    pub fn eq(self, other: Self) -> I<N> {
        unsafe { simd_eq(self, other) }
    }
}

#[repr(simd)]
pub struct I<const N: usize>([i32; N]);

impl<const N: usize> core::ops::BitAnd for I<N> {
    type Output = Self;
    fn bitand(self, other: Self) -> Self {
        unsafe { simd_and(self, other) }
    }
}

impl<const N: usize> I<N> {
    pub fn to_array(self) -> [bool; N] {
        let mut array = [false; N];
        let mut i = 0;
        while i < N {
            array[i] = self.0[i] == -1;
            i += 1;
        }
        array
    }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn bug() {
        let a = F::<64>::splat(0.);
        let b = F::<64>::splat(0.);
        let c = F::<64>::splat(0.);
        let m = a.eq(b) & a.eq(c);
        assert!(m.to_array()[0]);
    }
}

Meta

rustc --version --verbose:

rustc 1.53.0-nightly (138fd56cf 2021-04-02)
binary: rustc
commit-hash: 138fd56cf9598b4bf016634c768dca128a83a5d7
commit-date: 2021-04-02
host: x86_64-apple-darwin
release: 1.53.0-nightly
LLVM version: 12.0.0

Error output

   Compiling bug v0.1.0 (/Users/caleb/repos/bug)
error: could not compile `bug`

Caused by:
  process didn't exit successfully: `rustc --crate-name bug --edition=2018 src/lib.rs --error-format=json --json=diagnostic-rendered-ansi --emit=dep-info,link -C opt-level=3 -C embed-bitcode=no --test -C metadata=1974b6bb1d213572 -C extra-filename=-1974b6bb1d213572 --out-dir /Users/caleb/repos/bug/target/aarch64-apple-darwin/release/deps --target aarch64-apple-darwin -L dependency=/Users/caleb/repos/bug/target/aarch64-apple-darwin/release/deps -L dependency=/Users/caleb/repos/bug/target/release/deps` (signal: 11, SIGSEGV: invalid memory reference)
Backtrace

Backtrace from https://rust-lang.zulipchat.com/#narrow/stream/257879-project-portable-simd/topic/2021-03-29.20Meeting/near/232369790

* thread #9, name = 'LTO f64_ops.4vffyy4v-cgu.7', stop reason = EXC_BAD_ACCESS (code=1, address=0x8)
    frame #0: 0x0000000100473f7c librustc_driver-6566963bd0589bc0.dylib`llvm::Type::getTypeID() const + 12
    frame #1: 0x0000000100474468 librustc_driver-6566963bd0589bc0.dylib`llvm::Type::isVectorTy() const + 32
    frame #2: 0x000000010047453c librustc_driver-6566963bd0589bc0.dylib`llvm::Type::getScalarType() const + 32
    frame #3: 0x00000001007e4b68 librustc_driver-6566963bd0589bc0.dylib`llvm::Type::isIntOrIntVectorTy() const + 24
    frame #4: 0x000000010311a8b0 librustc_driver-6566963bd0589bc0.dylib`llvm::EVT::isExtendedInteger() const + 116
    frame #5: 0x000000010048cdb8 librustc_driver-6566963bd0589bc0.dylib`llvm::EVT::isInteger() const + 64
    frame #6: 0x000000010278d710 librustc_driver-6566963bd0589bc0.dylib`llvm::SelectionDAG::getNode(unsigned int, llvm::SDLoc const&, llvm::EVT, llvm::SDValue, llvm::SDNodeFlags) + 5776
    frame #7: 0x0000000102778264 librustc_driver-6566963bd0589bc0.dylib`llvm::SelectionDAG::getNode(unsigned int, llvm::SDLoc const&, llvm::EVT, llvm::SDValue) + 156
    frame #8: 0x000000010231db08 librustc_driver-6566963bd0589bc0.dylib`performExtendCombine(llvm::SDNode*, llvm::TargetLowering::DAGCombinerInfo&, llvm::SelectionDAG&) + 832
    frame #9: 0x0000000102317e48 librustc_driver-6566963bd0589bc0.dylib`llvm::AArch64TargetLowering::PerformDAGCombine(llvm::SDNode*, llvm::TargetLowering::DAGCombinerInfo&) const + 1128
    frame #10: 0x0000000102541298 librustc_driver-6566963bd0589bc0.dylib`(anonymous namespace)::DAGCombiner::combine(llvm::SDNode*) + 364
    frame #11: 0x000000010253a094 librustc_driver-6566963bd0589bc0.dylib`(anonymous namespace)::DAGCombiner::Run(llvm::CombineLevel) + 820
    frame #12: 0x0000000102539ce0 librustc_driver-6566963bd0589bc0.dylib`llvm::SelectionDAG::Combine(llvm::CombineLevel, llvm::AAResults*, llvm::CodeGenOpt::Level) + 92
    frame #13: 0x00000001027df038 librustc_driver-6566963bd0589bc0.dylib`llvm::SelectionDAGISel::CodeGenAndEmitDAG() + 1084
    frame #14: 0x00000001027deb8c librustc_driver-6566963bd0589bc0.dylib`llvm::SelectionDAGISel::SelectBasicBlock(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>, false, true>, bool&) + 352
    frame #15: 0x00000001027de010 librustc_driver-6566963bd0589bc0.dylib`llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) + 4444
    frame #16: 0x00000001027dbb98 librustc_driver-6566963bd0589bc0.dylib`llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 1568
    frame #17: 0x000000010229e0e8 librustc_driver-6566963bd0589bc0.dylib`(anonymous namespace)::AArch64DAGToDAGISel::runOnMachineFunction(llvm::MachineFunction&) + 56
    frame #18: 0x0000000102d18d00 librustc_driver-6566963bd0589bc0.dylib`llvm::MachineFunctionPass::runOnFunction(llvm::Function&) + 460
    frame #19: 0x000000010426b76c librustc_driver-6566963bd0589bc0.dylib`llvm::FPPassManager::runOnFunction(llvm::Function&) + 548
    frame #20: 0x0000000104272588 librustc_driver-6566963bd0589bc0.dylib`llvm::FPPassManager::runOnModule(llvm::Module&) + 116
    frame #21: 0x000000010426bfd8 librustc_driver-6566963bd0589bc0.dylib`(anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) + 688
    frame #22: 0x000000010426bb70 librustc_driver-6566963bd0589bc0.dylib`llvm::legacy::PassManagerImpl::run(llvm::Module&) + 272
    frame #23: 0x00000001042729a4 librustc_driver-6566963bd0589bc0.dylib`llvm::legacy::PassManager::run(llvm::Module&) + 36
    frame #24: 0x00000001003f9a58 librustc_driver-6566963bd0589bc0.dylib`LLVMRustWriteOutputFile + 696
    frame #25: 0x00000001003465a4 librustc_driver-6566963bd0589bc0.dylib`rustc_codegen_llvm::back::write::write_output_file::hc09c4bfb3a246709 + 356
  * frame #26: 0x0000000100344f60 librustc_driver-6566963bd0589bc0.dylib`rustc_codegen_llvm::back::write::codegen::with_codegen::h9282ea3405df7f19 + 140
    frame #27: 0x000000010034964c librustc_driver-6566963bd0589bc0.dylib`rustc_codegen_llvm::back::write::codegen::h18b6d47a71c14803 + 2616
    frame #28: 0x0000000100384f44 librustc_driver-6566963bd0589bc0.dylib`rustc_codegen_ssa::back::write::finish_intra_module_work::ha36a9bd9f4a0717d + 180
    frame #29: 0x00000001003802a8 librustc_driver-6566963bd0589bc0.dylib`rustc_codegen_ssa::back::write::execute_work_item::ha652a44c2011cc51 + 1228
    frame #30: 0x000000010038b80c librustc_driver-6566963bd0589bc0.dylib`std::sys_common::backtrace::__rust_begin_short_backtrace::he5bf95f074532528 + 180
    frame #31: 0x00000001003289e4 librustc_driver-6566963bd0589bc0.dylib`std::panicking::try::hc21045c482577b07 + 48
    frame #32: 0x000000010038e33c librustc_driver-6566963bd0589bc0.dylib`core::ops::function::FnOnce::call_once$u7b$$u7b$vtable.shim$u7d$$u7d$::hd4c96fd994a769dd + 144
    frame #33: 0x0000000115c4ee34 libstd-405150871270d457.dylib`_$LT$alloc..boxed..Box$LT$F$C$A$GT$$u20$as$u20$core..ops..function..FnOnce$LT$Args$GT$$GT$::call_once::hc929de8808b588b8 [inlined] _$LT$alloc..boxed..Box$LT$F$C$A$GT$$u20$as$u20$core..ops..function..FnOnce$LT$Args$GT$$GT$::call_once::h2b5dd4f23298a6af at boxed.rs:1546:9 [opt]
    frame #34: 0x0000000115c4ee28 libstd-405150871270d457.dylib`_$LT$alloc..boxed..Box$LT$F$C$A$GT$$u20$as$u20$core..ops..function..FnOnce$LT$Args$GT$$GT$::call_once::hc929de8808b588b8 at boxed.rs:1546 [opt]
    frame #35: 0x0000000115c5073c libstd-405150871270d457.dylib`std::sys::unix::thread::Thread::new::thread_start::hd74574d62a5c9da7 at thread.rs:71:17 [opt]

@calebzulawski calebzulawski added C-bug Category: This is a bug. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 8, 2021
@calebzulawski
Copy link
Member Author

@nagisa filed https://bugs.llvm.org/show_bug.cgi?id=49867 with the reduced LLVM IR from rustc, but I was only able to reproduce the segfault from rust with SIMD intrinsics with 64-length vectors, so I wonder if we have two separate bugs in the optimizer.

@jonas-schievink jonas-schievink added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-simd Area: SIMD (Single Instruction Multiple Data) O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state labels Apr 8, 2021
@nagisa
Copy link
Member

nagisa commented Apr 10, 2021

Yeah, those are two distinct issues. The reproduction steps provided in the thread here resulted in a different crash in the first place.

I was not able to reproduce this. In order for that to happen the reproducer probably should be made much more self contained – no cargo, no --test machinery, just a single rustc invocation (which may use libstd, but ideally doesn't)

@calebzulawski
Copy link
Member Author

calebzulawski commented Apr 10, 2021

Unfortunately I was not able to reproduce it without cargo test. I'm sure there's a way, but anything I wrote that looked like this example but outside of a test function did not crash. Perhaps tests have some subtle difference from say a simple executable that affects codegen (or maybe linking/LTO) in some way?

@nagisa nagisa added the requires-nightly This issue requires a nightly compiler in some way. label Apr 10, 2021
fanninpm pushed a commit to fanninpm/glacier that referenced this issue Jun 6, 2021
Code example extracted from comment [1].

[1]: rust-lang/rust#84020 (comment)
@rust-lang-glacier-bot rust-lang-glacier-bot added the glacier ICE tracked in rust-lang/glacier. label Jun 6, 2021
@workingjubilee
Copy link
Member

Does this still happen?

@Alexendoo
Copy link
Member

It no longer appears to happen since the LLVM 13 upgrade #87570

@nagisa nagisa added the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Nov 11, 2021
@BGR360
Copy link
Contributor

BGR360 commented Dec 27, 2021

I attempted to add the following test but couldn't get it to ICE on commit 138fd56 (the one OP reported the ICE on). I copied the compiler flags from rust-lang/glacier#954. Maybe somebody can figure out what I did wrong.

src/test/ui/simd/issue-84020.rs:

// edition: 2018
// compile-flags: --emit=dep-info,link -C opt-level=3 -C embed-bitcode=no --test -C metadata=1974b6bb1d213572 -C extra-filename=-1974b6bb1d213572 --target aarch64-apple-darwin

#![feature(const_generics, platform_intrinsics, repr_simd)]
#![allow(incomplete_features)]

extern "platform-intrinsic" {
    fn simd_eq<T, U>(a: T, b: T) -> U;
    fn simd_and<T>(a: T, b: T) -> T;
}

#[derive(Copy, Clone)]
#[repr(simd)]
pub struct F<const N: usize>([f32; N]);

impl<const N: usize> F<N> {
    pub fn splat(value: f32) -> Self {
        Self([value; N])
    }

    pub fn eq(self, other: Self) -> I<N> {
        unsafe { simd_eq(self, other) }
    }
}

#[repr(simd)]
pub struct I<const N: usize>([i32; N]);

impl<const N: usize> core::ops::BitAnd for I<N> {
    type Output = Self;
    fn bitand(self, other: Self) -> Self {
        unsafe { simd_and(self, other) }
    }
}

impl<const N: usize> I<N> {
    pub fn to_array(self) -> [bool; N] {
        let mut array = [false; N];
        let mut i = 0;
        while i < N {
            array[i] = self.0[i] == -1;
            i += 1;
        }
        array
    }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn bug() {
        let a = F::<64>::splat(0.);
        let b = F::<64>::splat(0.);
        let c = F::<64>::splat(0.);
        let m = a.eq(b) & a.eq(c);
        assert!(m.to_array()[0]);
    }
}

@workingjubilee workingjubilee added O-AArch64 Armv8-A or later processors in AArch64 mode E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example and removed O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state labels Mar 18, 2022
@workingjubilee
Copy link
Member

This lacks a clear reproducer, is mainly a bug in LLVM (not Rust), and apparently no longer happens. I am willing to leave this open for a while longer but it's a clear heisenbug that has questionable value on the tracker. I am leaving this note here for a future triage: if it hasn't gained an MCVE or test, maybe we should just chalk this issue up to the persistent tendency towards entropy in the universe and close it?

@BGR360
Copy link
Contributor

BGR360 commented Mar 23, 2022

chalk this issue up to the persistent tendency towards entropy in the universe

Probably best to file an issue for this and get it fixed /s

@nikic nikic removed the E-needs-test Call for participation: An issue has been fixed and does not reproduce, but no test has been added. label Mar 24, 2022
@workingjubilee workingjubilee added A-target-feature Area: Enabling/disabling target features like AVX, Neon, etc. and removed A-target-feature Area: Enabling/disabling target features like AVX, Neon, etc. labels Mar 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-simd Area: SIMD (Single Instruction Multiple Data) C-bug Category: This is a bug. E-needs-mcve Call for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example glacier ICE tracked in rust-lang/glacier. I-ICE Issue: The compiler panicked, giving an Internal Compilation Error (ICE) ❄️ O-AArch64 Armv8-A or later processors in AArch64 mode requires-nightly This issue requires a nightly compiler in some way. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

8 participants