From b706a02a098e18051860095d7439212e4637d1e4 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Thu, 20 Aug 2026 19:21:22 +0300 Subject: [PATCH 1/3] neon: drop the align requirement on vld1/vst1 lane loads and stores vld1 and vst1 lane intrinsics were dereferencing pointer directly which requires it to be aligned to the element type. (Too strict alignment requirements) The instructions don't requires alignment, so calling these with unaligned pointer caused UB. Lane loads and stores were updated to use `read_unaligned()` and `write_unaligned()` instead. --- .../core_arch/src/aarch64/neon/generated.rs | 4 +- crates/core_arch/src/aarch64/neon/mod.rs | 4 +- .../src/arm_shared/neon/generated.rs | 116 +++++++++--------- .../src/arm_shared/neon/load_tests.rs | 29 +++++ .../src/arm_shared/neon/store_tests.rs | 24 ++++ .../spec/neon/aarch64.spec.yml | 10 +- .../spec/neon/arm_shared.spec.yml | 43 +++---- 7 files changed, 131 insertions(+), 99 deletions(-) diff --git a/crates/core_arch/src/aarch64/neon/generated.rs b/crates/core_arch/src/aarch64/neon/generated.rs index 1b5b17e538..c471880919 100644 --- a/crates/core_arch/src/aarch64/neon/generated.rs +++ b/crates/core_arch/src/aarch64/neon/generated.rs @@ -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(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)"] @@ -25094,7 +25094,7 @@ pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_lane_f64(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)"] diff --git a/crates/core_arch/src/aarch64/neon/mod.rs b/crates/core_arch/src/aarch64/neon/mod.rs index c66702814c..e04c93ac1a 100644 --- a/crates/core_arch/src/aarch64/neon/mod.rs +++ b/crates/core_arch/src/aarch64/neon/mod.rs @@ -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(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. @@ -131,7 +131,7 @@ pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_lane_f64(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 diff --git a/crates/core_arch/src/arm_shared/neon/generated.rs b/crates/core_arch/src/arm_shared/neon/generated.rs index 3a47ede1ac..2c6f663d6e 100644 --- a/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/crates/core_arch/src/arm_shared/neon/generated.rs @@ -19307,7 +19307,7 @@ pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_lane_f16(ptr: *const f16, src: float16x4_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_f16)"] @@ -19327,7 +19327,7 @@ pub unsafe fn vld1_lane_f16(ptr: *const f16, src: float16x4_t) #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_f32)"] @@ -19352,7 +19352,7 @@ pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) )] pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) -> float32x2_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)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p16)"] @@ -19377,7 +19377,7 @@ pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) )] pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) -> poly16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p8)"] @@ -19402,7 +19402,7 @@ pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) - )] pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> poly8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s16)"] @@ -19427,7 +19427,7 @@ pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> p )] pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> int16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s32)"] @@ -19452,7 +19452,7 @@ pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> )] pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> int32x2_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)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s64)"] @@ -19462,7 +19462,7 @@ pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19477,7 +19477,7 @@ pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> )] pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> int64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s8)"] @@ -19502,7 +19502,7 @@ pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> )] pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> int8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u16)"] @@ -19527,7 +19527,7 @@ pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> in )] pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) -> uint16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u32)"] @@ -19552,7 +19552,7 @@ pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) - )] pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) -> uint32x2_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)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u64)"] @@ -19562,7 +19562,7 @@ pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19577,7 +19577,7 @@ pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) - )] pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) -> uint64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u8)"] @@ -19602,7 +19602,7 @@ pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) - )] pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> uint8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_f32)"] @@ -19627,7 +19627,7 @@ pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> u )] pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) -> float32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p16)"] @@ -19652,7 +19652,7 @@ pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) )] pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) -> poly16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p8)"] @@ -19677,7 +19677,7 @@ pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) )] pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> poly8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s16)"] @@ -19702,7 +19702,7 @@ pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> )] pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) -> int16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s32)"] @@ -19727,7 +19727,7 @@ pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) - )] pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) -> int32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s64)"] @@ -19737,7 +19737,7 @@ pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19752,7 +19752,7 @@ pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) - )] pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) -> int64x2_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)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s8)"] @@ -19777,7 +19777,7 @@ pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) - )] pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> int8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u16)"] @@ -19802,7 +19802,7 @@ pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> )] pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) -> uint16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u32)"] @@ -19827,7 +19827,7 @@ pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) )] pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) -> uint32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u64)"] @@ -19837,7 +19837,7 @@ pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19852,7 +19852,7 @@ pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) )] pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) -> uint64x2_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)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u8)"] @@ -19877,7 +19877,7 @@ pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) )] pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> uint8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p64)"] @@ -19887,7 +19887,7 @@ pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19902,7 +19902,7 @@ pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> )] pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) -> poly64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p64)"] @@ -19912,7 +19912,7 @@ pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) - #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19927,7 +19927,7 @@ pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) - )] pub unsafe fn vld1q_lane_p64(ptr: *const p64, src: poly64x2_t) -> poly64x2_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)) } #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p64)"] @@ -58579,7 +58579,7 @@ pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vst1_lane_f16(a: *mut f16, b: float16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::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_f16)"] @@ -58599,7 +58599,7 @@ pub unsafe fn vst1_lane_f16(a: *mut f16, b: float16x4_t) { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vst1q_lane_f16(a: *mut f16, b: float16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_f32)"] @@ -58624,7 +58624,7 @@ pub unsafe fn vst1q_lane_f16(a: *mut f16, b: float16x8_t) { )] pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::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_f32)"] @@ -58649,7 +58649,7 @@ pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { )] pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_s8)"] @@ -58674,7 +58674,7 @@ pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { )] pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::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_s8)"] @@ -58699,7 +58699,7 @@ pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { )] pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_s16)"] @@ -58724,7 +58724,7 @@ pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { )] pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::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_s16)"] @@ -58749,7 +58749,7 @@ pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { )] pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_s32)"] @@ -58774,7 +58774,7 @@ pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { )] pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::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_s32)"] @@ -58799,7 +58799,7 @@ pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { )] pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::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_s64)"] @@ -58824,7 +58824,7 @@ pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { )] pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_u8)"] @@ -58849,7 +58849,7 @@ pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { )] pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::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_u8)"] @@ -58874,7 +58874,7 @@ pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { )] pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_u16)"] @@ -58899,7 +58899,7 @@ pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { )] pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::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_u16)"] @@ -58924,7 +58924,7 @@ pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { )] pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_u32)"] @@ -58949,7 +58949,7 @@ pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { )] pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::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_u32)"] @@ -58974,7 +58974,7 @@ pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { )] pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::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_u64)"] @@ -58999,7 +58999,7 @@ pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { )] pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_p8)"] @@ -59024,7 +59024,7 @@ pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { )] pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::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_p8)"] @@ -59049,7 +59049,7 @@ pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { )] pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_p16)"] @@ -59074,7 +59074,7 @@ pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { )] pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::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_p16)"] @@ -59099,7 +59099,7 @@ pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { )] pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_p64)"] @@ -59124,7 +59124,7 @@ pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { )] pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_s64)"] @@ -59149,7 +59149,7 @@ pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { )] pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::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/vst1_lane_u64)"] @@ -59174,7 +59174,7 @@ pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { )] pub unsafe fn vst1_lane_u64(a: *mut u64, b: uint64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_p64_x2)"] @@ -61181,7 +61181,7 @@ unsafe fn vst1q_v8f16(addr: *const i8, val: float16x8_t, align: i32) { )] pub unsafe fn vst1q_lane_p64(a: *mut p64, b: poly64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::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_f16)"] diff --git a/crates/core_arch/src/arm_shared/neon/load_tests.rs b/crates/core_arch/src/arm_shared/neon/load_tests.rs index 70a37f7c05..ecb5cd53f4 100644 --- a/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -223,3 +223,32 @@ 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)); +} diff --git a/crates/core_arch/src/arm_shared/neon/store_tests.rs b/crates/core_arch/src/arm_shared/neon/store_tests.rs index 6eb60e4c78..68df3ec944 100644 --- a/crates/core_arch/src/arm_shared/neon/store_tests.rs +++ b/crates/core_arch/src/arm_shared/neon/store_tests.rs @@ -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); +} diff --git a/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index e5ce77ed8b..01942246a0 100644 --- a/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -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" @@ -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" diff --git a/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 7a7656e4c1..a91bfb2eb8 100644 --- a/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -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" @@ -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" @@ -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" @@ -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" @@ -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}" @@ -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}' @@ -14314,13 +14299,13 @@ intrinsics: - ['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'] + - ['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." @@ -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)." From 237ff08f2d4f41f95198473e6b5af8e0f1f61cd4 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Thu, 20 Aug 2026 20:32:59 +0300 Subject: [PATCH 2/3] neon: drop the align requirement on vld1 dup loads --- .../src/arm_shared/neon/generated.rs | 46 +++++++++---------- .../src/arm_shared/neon/load_tests.rs | 17 +++++++ .../spec/neon/arm_shared.spec.yml | 8 ++-- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/crates/core_arch/src/arm_shared/neon/generated.rs b/crates/core_arch/src/arm_shared/neon/generated.rs index 2c6f663d6e..b7cc4057ce 100644 --- a/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/crates/core_arch/src/arm_shared/neon/generated.rs @@ -18279,7 +18279,7 @@ pub unsafe fn vld1q_dup_f16(ptr: *const f16) -> float16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { - transmute(f32x2::splat(*ptr)) + transmute(f32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p16)"] @@ -18302,7 +18302,7 @@ pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { - transmute(u16x4::splat(*ptr)) + transmute(u16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p8)"] @@ -18325,7 +18325,7 @@ pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { - transmute(u8x8::splat(*ptr)) + transmute(u8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s16)"] @@ -18348,7 +18348,7 @@ pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { - transmute(i16x4::splat(*ptr)) + transmute(i16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s32)"] @@ -18371,7 +18371,7 @@ pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { - transmute(i32x2::splat(*ptr)) + transmute(i32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s8)"] @@ -18394,7 +18394,7 @@ pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { - transmute(i8x8::splat(*ptr)) + transmute(i8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u16)"] @@ -18417,7 +18417,7 @@ pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { - transmute(u16x4::splat(*ptr)) + transmute(u16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u32)"] @@ -18440,7 +18440,7 @@ pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { - transmute(u32x2::splat(*ptr)) + transmute(u32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u8)"] @@ -18463,7 +18463,7 @@ pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { - transmute(u8x8::splat(*ptr)) + transmute(u8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_f32)"] @@ -18486,7 +18486,7 @@ pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { - transmute(f32x4::splat(*ptr)) + transmute(f32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_p16)"] @@ -18509,7 +18509,7 @@ pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { - transmute(u16x8::splat(*ptr)) + transmute(u16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_p8)"] @@ -18532,7 +18532,7 @@ pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { - transmute(u8x16::splat(*ptr)) + transmute(u8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s16)"] @@ -18555,7 +18555,7 @@ pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { - transmute(i16x8::splat(*ptr)) + transmute(i16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s32)"] @@ -18578,7 +18578,7 @@ pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { - transmute(i32x4::splat(*ptr)) + transmute(i32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s64)"] @@ -18587,7 +18587,7 @@ pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18601,7 +18601,7 @@ pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { - transmute(i64x2::splat(*ptr)) + transmute(i64x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s8)"] @@ -18624,7 +18624,7 @@ pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { - transmute(i8x16::splat(*ptr)) + transmute(i8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u16)"] @@ -18647,7 +18647,7 @@ pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { - transmute(u16x8::splat(*ptr)) + transmute(u16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u32)"] @@ -18670,7 +18670,7 @@ pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { - transmute(u32x4::splat(*ptr)) + transmute(u32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u64)"] @@ -18679,7 +18679,7 @@ pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18693,7 +18693,7 @@ pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { - transmute(u64x2::splat(*ptr)) + transmute(u64x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u8)"] @@ -18716,7 +18716,7 @@ pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u8(ptr: *const u8) -> uint8x16_t { - transmute(u8x16::splat(*ptr)) + transmute(u8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p64)"] @@ -21734,7 +21734,7 @@ unsafe fn vld1q_v8f16(a: *const i8, b: i32) -> float16x8_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) diff --git a/crates/core_arch/src/arm_shared/neon/load_tests.rs b/crates/core_arch/src/arm_shared/neon/load_tests.rs index ecb5cd53f4..863fe87f61 100644 --- a/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -252,3 +252,20 @@ fn test_vld1q_lane_u64_unaligned() { }; assert_eq!(r, u64x2::new(10, e)); } + +#[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)); +} diff --git a/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index a91bfb2eb8..0f378dd9ef 100644 --- a/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -14381,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 @@ -14428,12 +14428,12 @@ intrinsics: - ['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_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)" From b36dd152f31e74c3ee7321e360a087570e09853f Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Fri, 21 Aug 2026 00:28:12 +0300 Subject: [PATCH 3/3] neon: assert ldr for the f32 lane and dup loads on arm --- .../core_arch/src/arm_shared/neon/generated.rs | 8 ++++---- .../core_arch/src/arm_shared/neon/load_tests.rs | 16 ++++++++++++++++ .../spec/neon/arm_shared.spec.yml | 8 ++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/crates/core_arch/src/arm_shared/neon/generated.rs b/crates/core_arch/src/arm_shared/neon/generated.rs index b7cc4057ce..12958f7b85 100644 --- a/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/crates/core_arch/src/arm_shared/neon/generated.rs @@ -18265,7 +18265,7 @@ pub unsafe fn vld1q_dup_f16(ptr: *const f16) -> float16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18472,7 +18472,7 @@ pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -19337,7 +19337,7 @@ pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr, LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19612,7 +19612,7 @@ pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 3))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr, LANE = 3))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 3) diff --git a/crates/core_arch/src/arm_shared/neon/load_tests.rs b/crates/core_arch/src/arm_shared/neon/load_tests.rs index 863fe87f61..a4db10f7c1 100644 --- a/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -253,6 +253,22 @@ fn test_vld1q_lane_u64_unaligned() { 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. diff --git a/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 0f378dd9ef..de82b203c1 100644 --- a/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -14295,10 +14295,10 @@ 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'] + - ['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'] @@ -14422,11 +14422,11 @@ 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', 'vld1.8', 'ld1r', 'i64x2::splat'] - ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vld1.8', 'ld1r', 'u64x2::splat']