Skip to content

rustc 1.14.0 beta producing neon instructions on armv7 #38402

New issue

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

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

Already on GitHub? # to your account

Closed
rillian opened this issue Dec 16, 2016 · 8 comments
Closed

rustc 1.14.0 beta producing neon instructions on armv7 #38402

rillian opened this issue Dec 16, 2016 · 8 comments
Labels
O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state

Comments

@rillian
Copy link
Contributor

rillian commented Dec 16, 2016

We have some SIGILL crashes from Firefox on Tegra 2 devices, apparently in Rust code. See https://bugzilla.mozilla.org/show_bug.cgi?id=1323773 or https://crash-stats.mozilla.com/report/index/c0d43287-b39c-422c-8609-d63c52161215 for a specific example. These are ARM Cortex-A9 SoC without the neon extension.

I didn't find the function in question in our official apk, but when I build the mp4parse_capi crate with rust 1.14.0-beta.3, I see vld and vst instructions in the rlib disassembly for the mp4parse_new() function.

I believe from recent commits that armv7 it intended to support non-neon devices like the Tegra 2 with this target triple. Perhaps #36933 was insufficient?

@rillian
Copy link
Contributor Author

rillian commented Dec 16, 2016

The stack trace suggests this might be an inlined Box::new(). I'm trying to produce a smaller test-case.

cc @alexcrichton

@rillian
Copy link
Contributor Author

rillian commented Dec 16, 2016

Here's a relatively small test-case:

//! Reduced neon test case from the mp4parse_capi crate.

pub struct Parser {
    state: State,
}

#[derive(Clone)]
pub struct State {
    // This struct must have at least two members to trigger
    // NEON code generation.
    pub u: u32,
    pub v: u32,
}

pub unsafe fn parser_new(state: *const State) -> *mut Parser {
    let parser = Box::new(Parser {
        state: (*state).clone(),
    });
    Box::into_raw(parser)
}

All of rustc 1.13.0-stable, 1.14.0-beta.3, and 1.15.0-nightly generate a vldr; vstr sequence in State as core::clone::Clone. Now I think perhaps I've misunderstood something!

@sanxiyn sanxiyn added the O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state label Dec 16, 2016
@alexcrichton
Copy link
Member

@rillian hm unfortunately I can't seem to reproduce with your test case. Could you gist the commands you're using to reproduce? Also, what target are you using for this?

@alexcrichton
Copy link
Member

alexcrichton commented Dec 16, 2016

Er, and to be concrete to what I'm seeing:

$ cat foo.rs

pub struct Parser {
    state: State,
}

#[derive(Clone)]
pub struct State {
    // This struct must have at least two members to trigger
    // NEON code generation.
    pub u: u32,
    pub v: u32,
}

#[no_mangle]
pub unsafe fn parser_new(state: *const State) -> *mut Parser {
    let parser = Box::new(Parser {
        state: (*state).clone(),
    });
    Box::into_raw(parser)

}

$ rustc +nightly -C opt-level=3 --target armv7-unknown-linux-gnueabihf foo.rs --crate-type lib --emit asm && cat foo.s
warning: field is never used: `state`, #[warn(dead_code)] on by default
 --> foo.rs:3:5
  |
3 |     state: State,
  |     ^^^^^^^^^^^^

	.text
	.syntax unified
	.eabi_attribute	67, "2.09"
	.eabi_attribute	6, 10
	.eabi_attribute	7, 65
	.eabi_attribute	8, 1
	.eabi_attribute	9, 2
	.fpu	vfpv3-d16
	.eabi_attribute	15, 1
	.eabi_attribute	16, 1
	.eabi_attribute	17, 2
	.eabi_attribute	20, 1
	.eabi_attribute	21, 1
	.eabi_attribute	23, 3
	.eabi_attribute	34, 1
	.eabi_attribute	24, 1
	.eabi_attribute	25, 1
	.eabi_attribute	28, 1
	.eabi_attribute	38, 1
	.eabi_attribute	14, 0
	.file	"foo.cgu-0.rs"
	.section	.text.parser_new,"ax",%progbits
	.globl	parser_new
	.p2align	2
	.type	parser_new,%function
parser_new:
	.fnstart
	.save	{r4, r5, r11, lr}
	push	{r4, r5, r11, lr}
	ldm	r0, {r4, r5}
	mov	r0, #8
	mov	r1, #4
	bl	__rust_allocate
	cmp	r0, #0
	stmne	r0, {r4, r5}
	popne	{r4, r5, r11, pc}
	bl	_ZN5alloc3oom3oom17h9abadf64e5736b05E
.Lfunc_end0:
	.size	parser_new, .Lfunc_end0-parser_new
	.fnend


	.section	".note.GNU-stack","",%progbits
	.eabi_attribute	30, 2

@rillian
Copy link
Contributor Author

rillian commented Dec 16, 2016

Sorry, I meant to include the command line. I was using:

$ $ rustup run nightly rustc --emit asm --crate-type=rlib --target armv7-linux-androideabi foo.rs && fgrep vld foo.s
warning: field is never used: `state`, #[warn(dead_code)] on by default
 --> foo.rs:4:5
  |
4 |     state: State,
  |     ^^^^^^^^^^^^

	vldr	d0, [r11, #-24]

@rillian
Copy link
Contributor Author

rillian commented Dec 16, 2016

Adding -O makes the vldr disappear.

@alexcrichton
Copy link
Member

@rillian oh for Android it's slightly different. #36933 only touched the Linux targets, not the Android ones.

For some reason I thought we still enabled NEON by default on armv7 Android b/c Google said it was required, but that's not the case apparently. In light of that it does indeed seem that we're missing a -neon in the target feature set of android.

Note that you can confirm NEON is enabled through:

$ rustc +nightly --print cfg --target armv7-linux-androideabi
debug_assertions                                      
target_arch="arm"                                     
target_endian="little"                                
target_env=""                                         
target_family="unix"                                  
target_feature="neon"                                 
target_feature="vfp2"                                 
target_feature="vfp3"                                 
target_has_atomic="16"                                
target_has_atomic="32"                                
target_has_atomic="64"                                
target_has_atomic="8"                                 
target_has_atomic="ptr"                               
target_os="android"                                   
target_pointer_width="32"                             
target_vendor="unknown"                               
unix                                                  

@rillian want to send a PR to disable neon by default on armv7 Android?

@rillian
Copy link
Contributor Author

rillian commented Dec 16, 2016

Aha! Thanks for explaining. I completely missed the android/gnu difference. I'll send a PR.

rillian added a commit to rillian/rust that referenced this issue Dec 16, 2016
We thought Google's ABI for arvm7 required neon, but it is
currently optional, perhaps because there is a significant
population of Tegra 2 devices still in use.

This turns off neon code generation outside #[target-feature]
blocks just like we do on armv7-unknown-linux-gnu, but unlike
most other armv7 targets. LLVM defaults to +neon for this target,
so an explicit disable is necessary.

See https://developer.android.com/ndk/guides/abis.html#v7a
for instruction set extension requirements.

Closes rust-lang#38402.
sanxiyn added a commit to sanxiyn/rust that referenced this issue Dec 19, 2016
rustc: Disable NEON on armv7 android.

We thought Google's ABI for arvm7 required neon, but it is
currently optional, perhaps because there is a significant
population of Tegra 2 devices still in use.

This turns off neon code generation outside #[target-feature]
blocks just like we do on armv7-unknown-linux-gnu, but unlike
most other armv7 targets. LLVM defaults to +neon for this target,
so an explicit disable is necessary.

See https://developer.android.com/ndk/guides/abis.html#v7a
for instruction set extension requirements.

Closes rust-lang#38402.
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
O-Arm Target: 32-bit Arm processors (armv6, armv7, thumb...), including 64-bit Arm in AArch32 state
Projects
None yet
Development

No branches or pull requests

3 participants