Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 283acf4

Browse files
Merge pull request rust-lang#422 from rust-lang/non-power-of-two-layout
Fix layout of non-power-of-two length vectors
2 parents f43e99a + d7d060a commit 283acf4

File tree

12 files changed

+201
-161
lines changed

12 files changed

+201
-161
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99
env:
1010
CARGO_NET_RETRY: 10
1111
RUSTUP_MAX_RETRIES: 10
12+
PROPTEST_CASES: 64
1213

1314
jobs:
1415
rustfmt:
@@ -181,6 +182,8 @@ jobs:
181182
cross-tests:
182183
name: "${{ matrix.target_feature }} on ${{ matrix.target }} (via cross)"
183184
runs-on: ubuntu-latest
185+
env:
186+
PROPTEST_CASES: 16
184187
strategy:
185188
fail-fast: false
186189

@@ -245,36 +248,10 @@ jobs:
245248
- name: Test (release)
246249
run: cross test --verbose --target=${{ matrix.target }} --release
247250

248-
features:
249-
name: "Test cargo features (${{ matrix.simd }} × ${{ matrix.features }})"
250-
runs-on: ubuntu-latest
251-
strategy:
252-
fail-fast: false
253-
matrix:
254-
simd:
255-
- ""
256-
- "avx512"
257-
features:
258-
- ""
259-
- "--features std"
260-
- "--features all_lane_counts"
261-
- "--all-features"
262-
263-
steps:
264-
- uses: actions/checkout@v2
265-
- name: Detect AVX512
266-
run: echo "CPU_FEATURE=$(lscpu | grep -o avx512[a-z]* | sed s/avx/+avx/ | tr '\n' ',' )" >> $GITHUB_ENV
267-
- name: Check build
268-
if: ${{ matrix.simd == '' }}
269-
run: RUSTFLAGS="-Dwarnings" cargo test --all-targets --no-default-features ${{ matrix.features }}
270-
- name: Check AVX
271-
if: ${{ matrix.simd == 'avx512' && contains(env.CPU_FEATURE, 'avx512') }}
272-
run: |
273-
echo "Found AVX features: $CPU_FEATURE"
274-
RUSTFLAGS="-Dwarnings -Ctarget-feature=$CPU_FEATURE" cargo test --all-targets --no-default-features ${{ matrix.features }}
275-
276251
miri:
277252
runs-on: ubuntu-latest
253+
env:
254+
PROPTEST_CASES: 16
278255
steps:
279256
- uses: actions/checkout@v2
280257
- name: Test (Miri)

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ members = [
55
"crates/std_float",
66
"crates/test_helpers",
77
]
8+
9+
[profile.test.package."*"]
10+
opt-level = 2
11+
12+
[profile.test.package.test_helpers]
13+
opt-level = 2

Cross.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[build.env]
2+
passthrough = ["PROPTEST_CASES"]

crates/core_simd/Cargo.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ categories = ["hardware-support", "no-std"]
99
license = "MIT OR Apache-2.0"
1010

1111
[features]
12-
default = ["as_crate"]
12+
default = ["as_crate", "std"]
1313
as_crate = []
1414
std = []
15-
all_lane_counts = []
1615

1716
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
1817
wasm-bindgen = "0.2"

crates/core_simd/src/lane_count.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,8 @@ macro_rules! supported_lane_count {
3333
};
3434
}
3535

36-
supported_lane_count!(1, 2, 4, 8, 16, 32, 64);
37-
#[cfg(feature = "all_lane_counts")]
3836
supported_lane_count!(
39-
3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
40-
31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
41-
56, 57, 58, 59, 60, 61, 62, 63
37+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
38+
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
39+
51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
4240
);

crates/core_simd/src/ops.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ macro_rules! int_divrem_guard {
7777
( $lhs:ident,
7878
$rhs:ident,
7979
{ const PANIC_ZERO: &'static str = $zero:literal;
80-
$simd_call:ident
80+
$simd_call:ident, $op:tt
8181
},
8282
$int:ident ) => {
8383
if $rhs.simd_eq(Simd::splat(0 as _)).any() {
@@ -96,8 +96,23 @@ macro_rules! int_divrem_guard {
9696
// Nice base case to make it easy to const-fold away the other branch.
9797
$rhs
9898
};
99-
// Safety: $lhs and rhs are vectors
100-
unsafe { core::intrinsics::simd::$simd_call($lhs, rhs) }
99+
100+
// aarch64 div fails for arbitrary `v % 0`, mod fails when rhs is MIN, for non-powers-of-two
101+
// these operations aren't vectorized on aarch64 anyway
102+
#[cfg(target_arch = "aarch64")]
103+
{
104+
let mut out = Simd::splat(0 as _);
105+
for i in 0..Self::LEN {
106+
out[i] = $lhs[i] $op rhs[i];
107+
}
108+
out
109+
}
110+
111+
#[cfg(not(target_arch = "aarch64"))]
112+
{
113+
// Safety: $lhs and rhs are vectors
114+
unsafe { core::intrinsics::simd::$simd_call($lhs, rhs) }
115+
}
101116
}
102117
};
103118
}
@@ -205,14 +220,14 @@ for_base_ops! {
205220
impl Div::div {
206221
int_divrem_guard {
207222
const PANIC_ZERO: &'static str = "attempt to divide by zero";
208-
simd_div
223+
simd_div, /
209224
}
210225
}
211226

212227
impl Rem::rem {
213228
int_divrem_guard {
214229
const PANIC_ZERO: &'static str = "attempt to calculate the remainder with a divisor of zero";
215-
simd_rem
230+
simd_rem, %
216231
}
217232
}
218233

crates/core_simd/src/simd/num/float.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,13 +255,41 @@ macro_rules! impl_trait {
255255
type Bits = Simd<$bits_ty, N>;
256256
type Cast<T: SimdElement> = Simd<T, N>;
257257

258+
#[cfg(not(target_arch = "aarch64"))]
258259
#[inline]
259260
fn cast<T: SimdCast>(self) -> Self::Cast<T>
260261
{
261262
// Safety: supported types are guaranteed by SimdCast
262263
unsafe { core::intrinsics::simd::simd_as(self) }
263264
}
264265

266+
// https://github.com/llvm/llvm-project/issues/94694
267+
#[cfg(target_arch = "aarch64")]
268+
#[inline]
269+
fn cast<T: SimdCast>(self) -> Self::Cast<T>
270+
{
271+
const { assert!(N <= 64) };
272+
if N <= 2 || N == 4 || N == 8 || N == 16 || N == 32 || N == 64 {
273+
// Safety: supported types are guaranteed by SimdCast
274+
unsafe { core::intrinsics::simd::simd_as(self) }
275+
} else if N < 4 {
276+
let x = self.resize::<4>(Default::default()).cast();
277+
x.resize::<N>(x[0])
278+
} else if N < 8 {
279+
let x = self.resize::<8>(Default::default()).cast();
280+
x.resize::<N>(x[0])
281+
} else if N < 16 {
282+
let x = self.resize::<16>(Default::default()).cast();
283+
x.resize::<N>(x[0])
284+
} else if N < 32 {
285+
let x = self.resize::<32>(Default::default()).cast();
286+
x.resize::<N>(x[0])
287+
} else {
288+
let x = self.resize::<64>(Default::default()).cast();
289+
x.resize::<N>(x[0])
290+
}
291+
}
292+
265293
#[inline]
266294
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
267295
unsafe fn to_int_unchecked<I: SimdCast>(self) -> Self::Cast<I>

crates/core_simd/src/vector.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ use crate::simd::{
9999
// directly constructing an instance of the type (i.e. `let vector = Simd(array)`) should be
100100
// avoided, as it will likely become illegal on `#[repr(simd)]` structs in the future. It also
101101
// causes rustc to emit illegal LLVM IR in some cases.
102-
#[repr(simd)]
102+
#[repr(simd, packed)]
103103
pub struct Simd<T, const N: usize>([T; N])
104104
where
105105
LaneCount<N>: SupportedLaneCount,

crates/core_simd/tests/layout.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#![feature(portable_simd)]
2+
3+
macro_rules! layout_tests {
4+
{ $($mod:ident, $ty:ty,)* } => {
5+
$(
6+
mod $mod {
7+
test_helpers::test_lanes! {
8+
fn no_padding<const LANES: usize>() {
9+
assert_eq!(
10+
core::mem::size_of::<core_simd::simd::Simd::<$ty, LANES>>(),
11+
core::mem::size_of::<[$ty; LANES]>(),
12+
);
13+
}
14+
}
15+
}
16+
)*
17+
}
18+
}
19+
20+
layout_tests! {
21+
i8, i8,
22+
i16, i16,
23+
i32, i32,
24+
i64, i64,
25+
isize, isize,
26+
u8, u8,
27+
u16, u16,
28+
u32, u32,
29+
u64, u64,
30+
usize, usize,
31+
f32, f32,
32+
f64, f64,
33+
mut_ptr, *mut (),
34+
const_ptr, *const (),
35+
}

crates/core_simd/tests/masks.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,6 @@ macro_rules! test_mask_api {
9999
assert_eq!(Mask::<$type, 2>::from_bitmask(bitmask), mask);
100100
}
101101

102-
#[cfg(feature = "all_lane_counts")]
103102
#[test]
104103
fn roundtrip_bitmask_conversion_odd() {
105104
let values = [

0 commit comments

Comments
 (0)