Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/core_arch/src/aarch64/neon/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25081,7 +25081,7 @@ pub unsafe fn vst1q_f64_x4(a: *mut f64, b: float64x2x4_t) {
#[stable(feature = "neon_intrinsics", since = "1.59.0")]
pub unsafe fn vst1_lane_f64<const LANE: i32>(a: *mut f64, b: float64x1_t) {
static_assert!(LANE == 0);
*a = simd_extract!(b, LANE as u32);
core::ptr::write_unaligned(a, simd_extract!(b, LANE as u32))
}
#[doc = "Store multiple single-element structures from one, two, three, or four registers"]
#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_f64)"]
Expand All @@ -25094,7 +25094,7 @@ pub unsafe fn vst1_lane_f64<const LANE: i32>(a: *mut f64, b: float64x1_t) {
#[stable(feature = "neon_intrinsics", since = "1.59.0")]
pub unsafe fn vst1q_lane_f64<const LANE: i32>(a: *mut f64, b: float64x2_t) {
static_assert_uimm_bits!(LANE, 1);
*a = simd_extract!(b, LANE as u32);
core::ptr::write_unaligned(a, simd_extract!(b, LANE as u32))
}
#[doc = "Store multiple 2-element structures from two registers"]
#[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst2_f64)"]
Expand Down
4 changes: 2 additions & 2 deletions crates/core_arch/src/aarch64/neon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub unsafe fn vld1q_dup_f64(ptr: *const f64) -> float64x2_t {
#[stable(feature = "neon_intrinsics", since = "1.59.0")]
pub unsafe fn vld1_lane_f64<const LANE: i32>(ptr: *const f64, src: float64x1_t) -> float64x1_t {
static_assert!(LANE == 0);
simd_insert!(src, LANE as u32, *ptr)
simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr))
}

/// Load one single-element structure to one lane of one register.
Expand All @@ -131,7 +131,7 @@ pub unsafe fn vld1_lane_f64<const LANE: i32>(ptr: *const f64, src: float64x1_t)
#[stable(feature = "neon_intrinsics", since = "1.59.0")]
pub unsafe fn vld1q_lane_f64<const LANE: i32>(ptr: *const f64, src: float64x2_t) -> float64x2_t {
static_assert_uimm_bits!(LANE, 1);
simd_insert!(src, LANE as u32, *ptr)
simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr))
}

/// Bitwise Select instructions. This instruction sets each bit in the destination SIMD&FP register
Expand Down
170 changes: 85 additions & 85 deletions crates/core_arch/src/arm_shared/neon/generated.rs

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions crates/core_arch/src/arm_shared/neon/load_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,65 @@ fn test_vld1q_f32() {
let r = unsafe { f32x4::from(vld1q_f32(a[1..].as_ptr())) };
assert_eq!(r, e)
}

#[simd_test(enable = "neon")]
fn test_vld1q_lane_u32_unaligned() {
// ld1 single-lane loads impose no alignment requirement: read from an odd byte offset.
let a: [u8; 5] = [0, 1, 2, 3, 4];
let e = u32::from_ne_bytes([1, 2, 3, 4]);
let src = u32x4::new(10, 11, 12, 13);
let r = unsafe {
u32x4::from(vld1q_lane_u32::<2>(
a.as_ptr().add(1) as *const u32,
src.into(),
))
};
assert_eq!(r, u32x4::new(10, 11, e, 13));
}

#[simd_test(enable = "neon")]
fn test_vld1q_lane_u64_unaligned() {
let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8];
let e = u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]);
let src = u64x2::new(10, 11);
let r = unsafe {
u64x2::from(vld1q_lane_u64::<1>(
a.as_ptr().add(1) as *const u64,
src.into(),
))
};
assert_eq!(r, u64x2::new(10, e));
}

#[simd_test(enable = "neon")]
fn test_vld1q_lane_f32_unaligned() {
// Float loads legalize differently from integer ones under low alignment
// (armv7 uses ldr + vmov), so the type class needs its own coverage.
let a: [u8; 5] = [0, 1, 2, 3, 4];
let e = f32::from_ne_bytes([1, 2, 3, 4]);
let src = f32x4::new(10., 11., 12., 13.);
let r = unsafe {
f32x4::from(vld1q_lane_f32::<2>(
a.as_ptr().add(1) as *const f32,
src.into(),
))
};
assert_eq!(r, f32x4::new(10., 11., e, 13.));
}

#[simd_test(enable = "neon")]
fn test_vld1q_dup_u32_unaligned() {
// ld1r replicate loads impose no alignment requirement either.
let a: [u8; 5] = [0, 1, 2, 3, 4];
let e = u32::from_ne_bytes([1, 2, 3, 4]);
let r = unsafe { u32x4::from(vld1q_dup_u32(a.as_ptr().add(1) as *const u32)) };
assert_eq!(r, u32x4::new(e, e, e, e));
}

#[simd_test(enable = "neon")]
fn test_vld1q_dup_u64_unaligned() {
let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8];
let e = u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]);
let r = unsafe { u64x2::from(vld1q_dup_u64(a.as_ptr().add(1) as *const u64)) };
assert_eq!(r, u64x2::new(e, e));
}
24 changes: 24 additions & 0 deletions crates/core_arch/src/arm_shared/neon/store_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,27 @@ fn test_vst1q_f32() {
assert_eq!(vals[3], 3.);
assert_eq!(vals[4], 4.);
}

#[simd_test(enable = "neon")]
fn test_vst1q_lane_u32_unaligned() {
// st1 single-lane stores impose no alignment requirement: write to an odd byte offset.
let mut vals = [0_u8; 5];
let a = u32x4::new(1, 2, 3, 4);
unsafe {
vst1q_lane_u32::<2>(vals.as_mut_ptr().add(1) as *mut u32, a.into());
}
assert_eq!(vals[0], 0);
assert_eq!(u32::from_ne_bytes([vals[1], vals[2], vals[3], vals[4]]), 3);
}

#[simd_test(enable = "neon")]
fn test_vst1q_lane_u64_unaligned() {
let mut vals = [0_u8; 9];
let a = u64x2::new(1, 2);
unsafe {
vst1q_lane_u64::<1>(vals.as_mut_ptr().add(1) as *mut u64, a.into());
}
assert_eq!(vals[0], 0);
let stored: [u8; 8] = vals[1..9].try_into().unwrap();
assert_eq!(u64::from_ne_bytes(stored), 2);
}
10 changes: 2 additions & 8 deletions crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4321,10 +4321,7 @@ intrinsics:
- ['*mut f64', float64x1_t]
compose:
- FnCall: [static_assert!, ['LANE == 0']]
- Assign:
- "*a"
- FnCall: [simd_extract!, [b, 'LANE as u32']]
- Identifier: [';', Symbol]
- FnCall: [core::ptr::write_unaligned, [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]]

- name: "vst1{neon_type[1].lane_nox}"
doc: "Store multiple single-element structures from one, two, three, or four registers"
Expand All @@ -4340,10 +4337,7 @@ intrinsics:
- ['*mut f64', float64x2_t]
compose:
- FnCall: [static_assert_uimm_bits!, [LANE, '1']]
- Assign:
- "*a"
- FnCall: [simd_extract!, [b, 'LANE as u32']]
- Identifier: [';', Symbol]
- FnCall: [core::ptr::write_unaligned, [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]]

- name: "vst2{neon_type[1].nox}"
doc: "Store multiple 2-element structures from two registers"
Expand Down
59 changes: 22 additions & 37 deletions crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2868,7 +2868,7 @@ intrinsics:
- ["*const f16", float16x8_t, 'q_lane', '3']
compose:
- FnCall: [static_assert_uimm_bits!, [LANE, '{type[3]}']]
- FnCall: [simd_insert!, [src, "LANE as u32", "*ptr"]]
- FnCall: [simd_insert!, [src, "LANE as u32", {FnCall: ["crate::ptr::read_unaligned", [ptr]]}]]

- name: "vld1{type[2]}_{neon_type[1]}"
doc: "Load one single-element structure and replicate to all lanes of one register"
Expand Down Expand Up @@ -4683,10 +4683,7 @@ intrinsics:
- ['*mut u64', uint64x1_t]
compose:
- FnCall: [static_assert!, ['LANE == 0']]
- Assign:
- "*a"
- FnCall: [simd_extract!, [b, 'LANE as u32']]
- Identifier: [';', Symbol]
- FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]]

- name: "vst1{neon_type[1].lane_nox}"
doc: "Store multiple single-element structures from one, two, three, or four registers"
Expand All @@ -4708,10 +4705,7 @@ intrinsics:
- ['*mut p64', poly64x1_t]
compose:
- FnCall: [static_assert!, ['LANE == 0']]
- Assign:
- "*a"
- FnCall: [simd_extract!, [b, 'LANE as u32']]
- Identifier: [';', Symbol]
- FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]]

- name: "vst1{neon_type[1].lane_nox}"
doc: "Store multiple single-element structures from one, two, three, or four registers"
Expand All @@ -4733,10 +4727,7 @@ intrinsics:
- ['*mut p64', poly64x2_t]
compose:
- FnCall: [static_assert_uimm_bits!, [LANE, '1']]
- Assign:
- "*a"
- FnCall: [simd_extract!, [b, 'LANE as u32']]
- Identifier: [';', Symbol]
- FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]]

- name: "vst1{neon_type[1].lane_nox}"
doc: "Store multiple single-element structures from one, two, three, or four registers"
Expand Down Expand Up @@ -4774,10 +4765,7 @@ intrinsics:
- ['*mut f32', float32x4_t, '2']
compose:
- FnCall: [static_assert_uimm_bits!, [LANE, "{type[2]}"]]
- Assign:
- "*a"
- FnCall: [simd_extract!, [b, 'LANE as u32']]
- Identifier: [';', Symbol]
- FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]]


- name: "vst1{neon_type[1].lane_nox}"
Expand All @@ -4799,10 +4787,7 @@ intrinsics:
- ['*mut f16', float16x8_t, '3']
compose:
- FnCall: [static_assert_uimm_bits!, [LANE, "{type[2]}"]]
- Assign:
- "*a"
- FnCall: [simd_extract!, [b, 'LANE as u32']]
- Identifier: [';', Symbol]
- FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]]


- name: 'vst1{neon_type[1].no}'
Expand Down Expand Up @@ -14310,17 +14295,17 @@ intrinsics:
- ['vld1q_lane_p16', '*const p16', 'poly16x8_t', '"vld1.16"', '7', 'ld1', 'static_assert_uimm_bits!', 'LANE, 3']
- ['vld1_lane_s32', '*const i32', 'int32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1_lane_u32', '*const u32', 'uint32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1_lane_f32', '*const f32', 'float32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1_lane_f32', '*const f32', 'float32x2_t', 'ldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1q_lane_s32', '*const i32', 'int32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2']
- ['vld1q_lane_u32', '*const u32', 'uint32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2']
- ['vld1q_lane_f32', '*const f32', 'float32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2']
- ['vld1_lane_s64', '*const i64', 'int64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0']
- ['vld1_lane_u64', '*const u64', 'uint64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0']
- ['vld1q_lane_s64', '*const i64', 'int64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1q_lane_u64', '*const u64', 'uint64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1q_lane_f32', '*const f32', 'float32x4_t', 'ldr', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2']
- ['vld1_lane_s64', '*const i64', 'int64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0']
- ['vld1_lane_u64', '*const u64', 'uint64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0']
- ['vld1q_lane_s64', '*const i64', 'int64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1q_lane_u64', '*const u64', 'uint64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
compose:
- FnCall: ["{type[6]}", ["{type[7]}"]]
- FnCall: [simd_insert!, [src, 'LANE as u32', '*ptr']]
- FnCall: [simd_insert!, [src, 'LANE as u32', {FnCall: ['crate::ptr::read_unaligned', [ptr]]}]]

- name: "{type[0]}"
doc: "Load one single-element structure to one lane of one register."
Expand All @@ -14338,11 +14323,11 @@ intrinsics:
safety:
unsafe: [neon]
types:
- ['vld1_lane_p64', '*const p64', 'poly64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0']
- ['vld1q_lane_p64', '*const p64', 'poly64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
- ['vld1_lane_p64', '*const p64', 'poly64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0']
- ['vld1q_lane_p64', '*const p64', 'poly64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1']
compose:
- FnCall: ["{type[6]}", ["{type[7]}"]]
- FnCall: [simd_insert!, [src, 'LANE as u32', '*ptr']]
- FnCall: [simd_insert!, [src, 'LANE as u32', {FnCall: ['crate::ptr::read_unaligned', [ptr]]}]]

- name: "{type[0]}"
doc: "Load one single-element structure and Replicate to all lanes (of one register)."
Expand Down Expand Up @@ -14396,7 +14381,7 @@ intrinsics:
safety:
unsafe: [neon]
types:
- ['vld1q_dup_p64', '*const p64', 'poly64x2_t', 'vldr', 'ld1r', 'vld1q_lane_p64::<0>', 'u64x2::splat(0)', '[0, 0]']
- ['vld1q_dup_p64', '*const p64', 'poly64x2_t', '"vld1.8"', 'ld1r', 'vld1q_lane_p64::<0>', 'u64x2::splat(0)', '[0, 0]']
compose:
- Let:
- x
Expand Down Expand Up @@ -14437,18 +14422,18 @@ intrinsics:

- ['vld1_dup_s32', '*const i32', 'int32x2_t', 'vld1.32', 'ld1r', 'i32x2::splat']
- ['vld1_dup_u32', '*const u32', 'uint32x2_t', 'vld1.32', 'ld1r', 'u32x2::splat']
- ['vld1_dup_f32', '*const f32', 'float32x2_t', 'vld1.32', 'ld1r', 'f32x2::splat']
- ['vld1_dup_f32', '*const f32', 'float32x2_t', 'ldr', 'ld1r', 'f32x2::splat']

- ['vld1q_dup_s32', '*const i32', 'int32x4_t', 'vld1.32', 'ld1r', 'i32x4::splat']
- ['vld1q_dup_u32', '*const u32', 'uint32x4_t', 'vld1.32', 'ld1r', 'u32x4::splat']
- ['vld1q_dup_f32', '*const f32', 'float32x4_t', 'vld1.32', 'ld1r', 'f32x4::splat']
- ['vld1q_dup_f32', '*const f32', 'float32x4_t', 'ldr', 'ld1r', 'f32x4::splat']

- ['vld1q_dup_s64', '*const i64', 'int64x2_t', 'vldr', 'ld1r', 'i64x2::splat']
- ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vldr', 'ld1r', 'u64x2::splat']
- ['vld1q_dup_s64', '*const i64', 'int64x2_t', 'vld1.8', 'ld1r', 'i64x2::splat']
- ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vld1.8', 'ld1r', 'u64x2::splat']
compose:
- FnCall:
- transmute
- - FnCall: ['{type[5]}', ["*ptr"]]
- - FnCall: ['{type[5]}', [{FnCall: ['crate::ptr::read_unaligned', [ptr]]}]]

- name: "{type[0]}"
doc: "Absolute difference and accumulate (64-bit)"
Expand Down
Loading