Skip to content

Commit d31e8a4

Browse files
committed
allow array-style simd in inline asm
1 parent c781584 commit d31e8a4

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

compiler/rustc_hir_analysis/src/check/intrinsicck.rs

+25-13
Original file line numberDiff line numberDiff line change
@@ -84,33 +84,45 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
8484
ty::Adt(adt, substs) if adt.repr().simd() => {
8585
let fields = &adt.non_enum_variant().fields;
8686
let elem_ty = fields[FieldIdx::from_u32(0)].ty(self.tcx, substs);
87-
match elem_ty.kind() {
88-
ty::Never | ty::Error(_) => return None,
89-
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => {
90-
Some(InlineAsmType::VecI8(fields.len() as u64))
87+
88+
let (size, ty) = match elem_ty.kind() {
89+
ty::Array(ty, len) => {
90+
if let Some(len) =
91+
len.try_eval_target_usize(self.tcx, self.tcx.param_env(adt.did()))
92+
{
93+
(len, *ty)
94+
} else {
95+
return None;
96+
}
9197
}
98+
_ => (fields.len() as u64, elem_ty),
99+
};
100+
101+
match ty.kind() {
102+
ty::Never | ty::Error(_) => return None,
103+
ty::Int(IntTy::I8) | ty::Uint(UintTy::U8) => Some(InlineAsmType::VecI8(size)),
92104
ty::Int(IntTy::I16) | ty::Uint(UintTy::U16) => {
93-
Some(InlineAsmType::VecI16(fields.len() as u64))
105+
Some(InlineAsmType::VecI16(size))
94106
}
95107
ty::Int(IntTy::I32) | ty::Uint(UintTy::U32) => {
96-
Some(InlineAsmType::VecI32(fields.len() as u64))
108+
Some(InlineAsmType::VecI32(size))
97109
}
98110
ty::Int(IntTy::I64) | ty::Uint(UintTy::U64) => {
99-
Some(InlineAsmType::VecI64(fields.len() as u64))
111+
Some(InlineAsmType::VecI64(size))
100112
}
101113
ty::Int(IntTy::I128) | ty::Uint(UintTy::U128) => {
102-
Some(InlineAsmType::VecI128(fields.len() as u64))
114+
Some(InlineAsmType::VecI128(size))
103115
}
104116
ty::Int(IntTy::Isize) | ty::Uint(UintTy::Usize) => {
105117
Some(match self.tcx.sess.target.pointer_width {
106-
16 => InlineAsmType::VecI16(fields.len() as u64),
107-
32 => InlineAsmType::VecI32(fields.len() as u64),
108-
64 => InlineAsmType::VecI64(fields.len() as u64),
118+
16 => InlineAsmType::VecI16(size),
119+
32 => InlineAsmType::VecI32(size),
120+
64 => InlineAsmType::VecI64(size),
109121
_ => unreachable!(),
110122
})
111123
}
112-
ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(fields.len() as u64)),
113-
ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(fields.len() as u64)),
124+
ty::Float(FloatTy::F32) => Some(InlineAsmType::VecF32(size)),
125+
ty::Float(FloatTy::F64) => Some(InlineAsmType::VecF64(size)),
114126
_ => None,
115127
}
116128
}

tests/assembly/asm/inline-asm-avx.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// assembly-output: emit-asm
2+
// compile-flags: --crate-type=lib
3+
// only-x86_64
4+
// ignore-sgx
5+
6+
#![feature(portable_simd)]
7+
8+
use std::simd::Simd;
9+
use std::arch::asm;
10+
11+
#[target_feature(enable = "avx")]
12+
#[no_mangle]
13+
// CHECK-LABEL: convert:
14+
pub unsafe fn convert(a: *const f32) -> Simd<f32, 8> {
15+
// CHECK: vbroadcastss (%{{[er][a-ds0-9][xpi0-9]?}}), {{%ymm[0-7]}}
16+
let b: Simd<f32, 8>;
17+
unsafe {
18+
asm!(
19+
"vbroadcastss {b}, [{a}]",
20+
a = in(reg) a,
21+
b = out(ymm_reg) b,
22+
);
23+
}
24+
b
25+
}

0 commit comments

Comments
 (0)