Skip to content

Commit 8451656

Browse files
committed
Fix maximum SIMD lane count, and expose it to other crates. Disallow SIMD vectors with non-power-of-two lengths.
1 parent 07db2bf commit 8451656

17 files changed

+148
-169
lines changed

compiler/rustc_middle/src/ty/layout.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,13 @@ pub const FAT_PTR_ADDR: usize = 0;
165165
/// - For a slice, this is the length.
166166
pub const FAT_PTR_EXTRA: usize = 1;
167167

168+
/// The maximum supported number of lanes in a SIMD vector.
169+
///
170+
/// This value is selected based on backend support:
171+
/// * LLVM does not appear to have a vector width limit.
172+
/// * Cranelift stores the base-2 log of the lane count in a 4 bit integer.
173+
pub const MAX_SIMD_LANES: u64 = 1 << 0xF;
174+
168175
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable)]
169176
pub enum LayoutError<'tcx> {
170177
Unknown(Ty<'tcx>),
@@ -700,10 +707,15 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
700707
// Can't be caught in typeck if the array length is generic.
701708
if e_len == 0 {
702709
tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty));
703-
} else if e_len > 65536 {
710+
} else if !e_len.is_power_of_two() {
704711
tcx.sess.fatal(&format!(
705-
"monomorphising SIMD type `{}` of length greater than 65536",
706-
ty,
712+
"monomorphising SIMD type `{}` of non-power-of-two length",
713+
ty
714+
));
715+
} else if e_len > MAX_SIMD_LANES {
716+
tcx.sess.fatal(&format!(
717+
"monomorphising SIMD type `{}` of length greater than {}",
718+
ty, MAX_SIMD_LANES,
707719
));
708720
}
709721

compiler/rustc_typeck/src/check/check.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_hir::{ItemKind, Node};
1212
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
1313
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
1414
use rustc_middle::ty::fold::TypeFoldable;
15+
use rustc_middle::ty::layout::MAX_SIMD_LANES;
1516
use rustc_middle::ty::subst::GenericArgKind;
1617
use rustc_middle::ty::util::{Discr, IntTypeExt, Representability};
1718
use rustc_middle::ty::{self, ParamEnv, RegionKind, ToPredicate, Ty, TyCtxt};
@@ -1108,12 +1109,22 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
11081109
if len == 0 {
11091110
struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit();
11101111
return;
1111-
} else if len > 65536 {
1112+
} else if !len.is_power_of_two() {
11121113
struct_span_err!(
11131114
tcx.sess,
11141115
sp,
11151116
E0075,
1116-
"SIMD vector cannot have more than 65536 elements"
1117+
"SIMD vector length must be a power of two"
1118+
)
1119+
.emit();
1120+
return;
1121+
} else if len > MAX_SIMD_LANES {
1122+
struct_span_err!(
1123+
tcx.sess,
1124+
sp,
1125+
E0075,
1126+
"SIMD vector cannot have more than {} elements",
1127+
MAX_SIMD_LANES,
11171128
)
11181129
.emit();
11191130
return;

src/test/ui/consts/const-eval/simd/insert_extract.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
#[repr(simd)] struct i8x1(i8);
1010
#[repr(simd)] struct u16x2(u16, u16);
11-
#[repr(simd)] struct f32x3(f32, f32, f32);
11+
#[repr(simd)] struct f32x4(f32, f32, f32, f32);
1212

1313
extern "platform-intrinsic" {
1414
#[rustc_const_stable(feature = "foo", since = "1.3.37")]
@@ -39,19 +39,23 @@ fn main() {
3939
assert_eq!(Y1, 42);
4040
}
4141
{
42-
const U: f32x3 = f32x3(13., 14., 15.);
43-
const V: f32x3 = unsafe { simd_insert(U, 1_u32, 42_f32) };
42+
const U: f32x4 = f32x4(13., 14., 15., 16.);
43+
const V: f32x4 = unsafe { simd_insert(U, 1_u32, 42_f32) };
4444
const X0: f32 = V.0;
4545
const X1: f32 = V.1;
4646
const X2: f32 = V.2;
47+
const X3: f32 = V.3;
4748
const Y0: f32 = unsafe { simd_extract(V, 0) };
4849
const Y1: f32 = unsafe { simd_extract(V, 1) };
4950
const Y2: f32 = unsafe { simd_extract(V, 2) };
51+
const Y3: f32 = unsafe { simd_extract(V, 3) };
5052
assert_eq!(X0, 13.);
5153
assert_eq!(X1, 42.);
5254
assert_eq!(X2, 15.);
55+
assert_eq!(X3, 16.);
5356
assert_eq!(Y0, 13.);
5457
assert_eq!(Y1, 42.);
5558
assert_eq!(Y2, 15.);
59+
assert_eq!(Y3, 16.);
5660
}
5761
}

src/test/ui/issues/issue-17170.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// run-pass
21
#![feature(repr_simd)]
32

43
#[repr(simd)]
54
struct T(f64, f64, f64);
5+
//~^ ERROR SIMD vector length must be a power of two
66

77
static X: T = T(0.0, 0.0, 0.0);
88

src/test/ui/issues/issue-17170.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0075]: SIMD vector length must be a power of two
2+
--> $DIR/issue-17170.rs:4:1
3+
|
4+
LL | struct T(f64, f64, f64);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: monomorphising SIMD type `T` of non-power-of-two length
8+
9+
error: aborting due to 2 previous errors
10+
11+
For more information about this error, try `rustc --explain E0075`.

src/test/ui/issues/issue-39720.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
// run-pass
21
// ignore-emscripten FIXME(#45351)
32

43
#![feature(repr_simd, platform_intrinsics)]
54

65
#[repr(simd)]
76
#[derive(Copy, Clone, Debug)]
87
pub struct Char3(pub i8, pub i8, pub i8);
8+
//~^ ERROR SIMD vector length must be a power of two
99

1010
#[repr(simd)]
1111
#[derive(Copy, Clone, Debug)]
1212
pub struct Short3(pub i16, pub i16, pub i16);
13+
//~^ ERROR SIMD vector length must be a power of two
1314

1415
extern "platform-intrinsic" {
1516
fn simd_cast<T, U>(x: T) -> U;

src/test/ui/issues/issue-39720.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error[E0075]: SIMD vector length must be a power of two
2+
--> $DIR/issue-39720.rs:7:1
3+
|
4+
LL | pub struct Char3(pub i8, pub i8, pub i8);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error[E0075]: SIMD vector length must be a power of two
8+
--> $DIR/issue-39720.rs:12:1
9+
|
10+
LL | pub struct Short3(pub i16, pub i16, pub i16);
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+
15+
For more information about this error, try `rustc --explain E0075`.

src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs

+2-17
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@ struct i32x2(i32, i32);
99
#[repr(simd)]
1010
#[derive(Copy, Clone)]
1111
#[allow(non_camel_case_types)]
12-
struct i32x3(i32, i32, i32);
13-
#[repr(simd)]
14-
#[derive(Copy, Clone)]
15-
#[allow(non_camel_case_types)]
1612
struct i32x4(i32, i32, i32, i32);
1713
#[repr(simd)]
1814
#[derive(Copy, Clone)]
@@ -27,10 +23,6 @@ struct f32x2(f32, f32);
2723
#[repr(simd)]
2824
#[derive(Copy, Clone)]
2925
#[allow(non_camel_case_types)]
30-
struct f32x3(f32, f32, f32);
31-
#[repr(simd)]
32-
#[derive(Copy, Clone)]
33-
#[allow(non_camel_case_types)]
3426
struct f32x4(f32, f32, f32, f32);
3527
#[repr(simd)]
3628
#[derive(Copy, Clone)]
@@ -43,7 +35,6 @@ extern "platform-intrinsic" {
4335
fn simd_extract<T, E>(x: T, idx: u32) -> E;
4436

4537
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
46-
fn simd_shuffle3<T, U>(x: T, y: T, idx: [u32; 3]) -> U;
4738
fn simd_shuffle4<T, U>(x: T, y: T, idx: [u32; 4]) -> U;
4839
fn simd_shuffle8<T, U>(x: T, y: T, idx: [u32; 8]) -> U;
4940
}
@@ -61,28 +52,22 @@ fn main() {
6152

6253
simd_shuffle2::<i32, i32>(0, 0, [0; 2]);
6354
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
64-
simd_shuffle3::<i32, i32>(0, 0, [0; 3]);
65-
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
6655
simd_shuffle4::<i32, i32>(0, 0, [0; 4]);
6756
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
6857
simd_shuffle8::<i32, i32>(0, 0, [0; 8]);
6958
//~^ ERROR expected SIMD input type, found non-SIMD `i32`
7059

7160
simd_shuffle2::<_, f32x2>(x, x, [0; 2]);
7261
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
73-
simd_shuffle3::<_, f32x3>(x, x, [0; 3]);
74-
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32`
7562
simd_shuffle4::<_, f32x4>(x, x, [0; 4]);
7663
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
7764
simd_shuffle8::<_, f32x8>(x, x, [0; 8]);
7865
//~^ ERROR element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
7966

8067
simd_shuffle2::<_, i32x8>(x, x, [0; 2]);
8168
//~^ ERROR expected return type of length 2, found `i32x8` with length 8
82-
simd_shuffle3::<_, i32x4>(x, x, [0; 3]);
83-
//~^ ERROR expected return type of length 3, found `i32x4` with length 4
84-
simd_shuffle4::<_, i32x3>(x, x, [0; 4]);
85-
//~^ ERROR expected return type of length 4, found `i32x3` with length 3
69+
simd_shuffle4::<_, i32x8>(x, x, [0; 4]);
70+
//~^ ERROR expected return type of length 4, found `i32x8` with length 8
8671
simd_shuffle8::<_, i32x2>(x, x, [0; 8]);
8772
//~^ ERROR expected return type of length 8, found `i32x2` with length 2
8873
}
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,75 @@
11
error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32`
2-
--> $DIR/simd-intrinsic-generic-elements.rs:55:9
2+
--> $DIR/simd-intrinsic-generic-elements.rs:46:9
33
|
44
LL | simd_insert(0, 0, 0);
55
| ^^^^^^^^^^^^^^^^^^^^
66

77
error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64`
8-
--> $DIR/simd-intrinsic-generic-elements.rs:57:9
8+
--> $DIR/simd-intrinsic-generic-elements.rs:48:9
99
|
1010
LL | simd_insert(x, 0, 1.0);
1111
| ^^^^^^^^^^^^^^^^^^^^^^
1212

1313
error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32`
14-
--> $DIR/simd-intrinsic-generic-elements.rs:59:9
14+
--> $DIR/simd-intrinsic-generic-elements.rs:50:9
1515
|
1616
LL | simd_extract::<_, f32>(x, 0);
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818

1919
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32`
20-
--> $DIR/simd-intrinsic-generic-elements.rs:62:9
20+
--> $DIR/simd-intrinsic-generic-elements.rs:53:9
2121
|
2222
LL | simd_shuffle2::<i32, i32>(0, 0, [0; 2]);
2323
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2424

25-
error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected SIMD input type, found non-SIMD `i32`
26-
--> $DIR/simd-intrinsic-generic-elements.rs:64:9
27-
|
28-
LL | simd_shuffle3::<i32, i32>(0, 0, [0; 3]);
29-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30-
3125
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32`
32-
--> $DIR/simd-intrinsic-generic-elements.rs:66:9
26+
--> $DIR/simd-intrinsic-generic-elements.rs:55:9
3327
|
3428
LL | simd_shuffle4::<i32, i32>(0, 0, [0; 4]);
3529
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3630

3731
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32`
38-
--> $DIR/simd-intrinsic-generic-elements.rs:68:9
32+
--> $DIR/simd-intrinsic-generic-elements.rs:57:9
3933
|
4034
LL | simd_shuffle8::<i32, i32>(0, 0, [0; 8]);
4135
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4236

4337
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32`
44-
--> $DIR/simd-intrinsic-generic-elements.rs:71:9
38+
--> $DIR/simd-intrinsic-generic-elements.rs:60:9
4539
|
4640
LL | simd_shuffle2::<_, f32x2>(x, x, [0; 2]);
4741
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4842

49-
error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32`
50-
--> $DIR/simd-intrinsic-generic-elements.rs:73:9
51-
|
52-
LL | simd_shuffle3::<_, f32x3>(x, x, [0; 3]);
53-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
54-
5543
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32`
56-
--> $DIR/simd-intrinsic-generic-elements.rs:75:9
44+
--> $DIR/simd-intrinsic-generic-elements.rs:62:9
5745
|
5846
LL | simd_shuffle4::<_, f32x4>(x, x, [0; 4]);
5947
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6048

6149
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32`
62-
--> $DIR/simd-intrinsic-generic-elements.rs:77:9
50+
--> $DIR/simd-intrinsic-generic-elements.rs:64:9
6351
|
6452
LL | simd_shuffle8::<_, f32x8>(x, x, [0; 8]);
6553
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6654

6755
error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8
68-
--> $DIR/simd-intrinsic-generic-elements.rs:80:9
56+
--> $DIR/simd-intrinsic-generic-elements.rs:67:9
6957
|
7058
LL | simd_shuffle2::<_, i32x8>(x, x, [0; 2]);
7159
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7260

73-
error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return type of length 3, found `i32x4` with length 4
74-
--> $DIR/simd-intrinsic-generic-elements.rs:82:9
61+
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x8` with length 8
62+
--> $DIR/simd-intrinsic-generic-elements.rs:69:9
7563
|
76-
LL | simd_shuffle3::<_, i32x4>(x, x, [0; 3]);
77-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
78-
79-
error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x3` with length 3
80-
--> $DIR/simd-intrinsic-generic-elements.rs:84:9
81-
|
82-
LL | simd_shuffle4::<_, i32x3>(x, x, [0; 4]);
64+
LL | simd_shuffle4::<_, i32x8>(x, x, [0; 4]);
8365
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8466

8567
error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2
86-
--> $DIR/simd-intrinsic-generic-elements.rs:86:9
68+
--> $DIR/simd-intrinsic-generic-elements.rs:71:9
8769
|
8870
LL | simd_shuffle8::<_, i32x2>(x, x, [0; 8]);
8971
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
9072

91-
error: aborting due to 15 previous errors
73+
error: aborting due to 12 previous errors
9274

9375
For more information about this error, try `rustc --explain E0511`.

src/test/ui/simd-type-generic-monomorphisation-oversized.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
#![feature(repr_simd, platform_intrinsics)]
44

5-
// error-pattern:monomorphising SIMD type `Simd<65537_usize>` of length greater than 65536
5+
// error-pattern:monomorphising SIMD type `Simd<65536_usize>` of length greater than 32768
66

77
#[repr(simd)]
88
struct Simd<const N: usize>([f32; N]);
99

1010
fn main() {
11-
let _ = Simd::<65537>([0.; 65537]);
11+
let _ = Simd::<65536>([0.; 65536]);
1212
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: monomorphising SIMD type `Simd<65537_usize>` of length greater than 65536
1+
error: monomorphising SIMD type `Simd<65536_usize>` of length greater than 32768
22

33
error: aborting due to previous error
44

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// build-fail
2+
3+
#![feature(repr_simd, platform_intrinsics)]
4+
5+
// error-pattern:monomorphising SIMD type `Simd<3_usize>` of non-power-of-two length
6+
7+
#[repr(simd)]
8+
struct Simd<const N: usize>([f32; N]);
9+
10+
fn main() {
11+
let _ = Simd::<3>([0.; 3]);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
error: monomorphising SIMD type `Simd<3_usize>` of non-power-of-two length
2+
3+
error: aborting due to previous error
4+

src/test/ui/simd-type.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ struct empty; //~ ERROR SIMD vector cannot be empty
99
#[repr(simd)]
1010
struct empty2([f32; 0]); //~ ERROR SIMD vector cannot be empty
1111

12+
#[repr(simd)]
13+
struct pow2([f32; 7]); //~ ERROR SIMD vector length must be a power of two
14+
1215
#[repr(simd)]
1316
struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous
1417

@@ -21,9 +24,9 @@ struct FooV(Foo, Foo); //~ ERROR SIMD vector element type should be a primitive
2124
struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type
2225

2326
#[repr(simd)]
24-
struct TooBig([f32; 65537]); //~ ERROR SIMD vector cannot have more than 65536 elements
27+
struct TooBig([f32; 65536]); //~ ERROR SIMD vector cannot have more than 32768 elements
2528

2629
#[repr(simd)]
27-
struct JustRight([u128; 65536]);
30+
struct JustRight([u128; 32768]);
2831

2932
fn main() {}

0 commit comments

Comments
 (0)