From d122a0813acc162805683eb207a3a9e659c462d5 Mon Sep 17 00:00:00 2001 From: George O'Hara Date: Mon, 27 Sep 2021 13:18:22 +0100 Subject: [PATCH] Issue 89193 --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 33 +++++++++--- src/test/ui/simd/issue-89193.rs | 53 ++++++++++++++++++++ 2 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/simd/issue-89193.rs diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 37b3279fb80..8494baaa56d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -20,7 +20,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; use rustc_span::{sym, symbol::kw, Span, Symbol}; use rustc_target::abi::{self, HasDataLayout, Primitive}; -use rustc_target::spec::PanicStrategy; +use rustc_target::spec::{HasTargetSpec, PanicStrategy}; use std::cmp::Ordering; use std::iter; @@ -1187,11 +1187,28 @@ fn generic_simd_intrinsic( // FIXME: use: // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Function.h#L182 // https://github.com/llvm-mirror/llvm/blob/master/include/llvm/IR/Intrinsics.h#L81 - fn llvm_vector_str(elem_ty: Ty<'_>, vec_len: u64, no_pointers: usize) -> String { + fn llvm_vector_str( + elem_ty: Ty<'_>, + vec_len: u64, + no_pointers: usize, + bx: &Builder<'a, 'll, 'tcx>, + ) -> String { let p0s: String = "p0".repeat(no_pointers); match *elem_ty.kind() { - ty::Int(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), - ty::Uint(v) => format!("v{}{}i{}", vec_len, p0s, v.bit_width().unwrap()), + ty::Int(v) => format!( + "v{}{}i{}", + vec_len, + p0s, + // Normalize to prevent crash if v: IntTy::Isize + v.normalize(bx.target_spec().pointer_width).bit_width().unwrap() + ), + ty::Uint(v) => format!( + "v{}{}i{}", + vec_len, + p0s, + // Normalize to prevent crash if v: UIntTy::Usize + v.normalize(bx.target_spec().pointer_width).bit_width().unwrap() + ), ty::Float(v) => format!("v{}{}f{}", vec_len, p0s, v.bit_width()), _ => unreachable!(), } @@ -1327,11 +1344,11 @@ fn generic_simd_intrinsic( // Type of the vector of pointers: let llvm_pointer_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count); - let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count); + let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count, bx); // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count - 1); - let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1); + let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1, bx); let llvm_intrinsic = format!("llvm.masked.gather.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); @@ -1455,11 +1472,11 @@ fn generic_simd_intrinsic( // Type of the vector of pointers: let llvm_pointer_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count); - let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count); + let llvm_pointer_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count, bx); // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, underlying_ty, in_len, pointer_count - 1); - let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1); + let llvm_elem_vec_str = llvm_vector_str(underlying_ty, in_len, pointer_count - 1, bx); let llvm_intrinsic = format!("llvm.masked.scatter.{}.{}", llvm_elem_vec_str, llvm_pointer_vec_str); diff --git a/src/test/ui/simd/issue-89193.rs b/src/test/ui/simd/issue-89193.rs new file mode 100644 index 00000000000..d6ebea10b7a --- /dev/null +++ b/src/test/ui/simd/issue-89193.rs @@ -0,0 +1,53 @@ +// run-pass + +// Test that simd gather instructions on slice of usize don't cause crash +// See issue #89183 - https://github.com/rust-lang/rust/issues/89193 + +#![feature(repr_simd, platform_intrinsics)] +#![allow(non_camel_case_types)] + +#[repr(simd)] +#[derive(Copy, Clone, PartialEq, Debug)] +struct x4(pub T, pub T, pub T, pub T); + +extern "platform-intrinsic" { + fn simd_gather(x: T, y: U, z: V) -> T; +} + +fn main() { + let x: [usize; 4] = [10, 11, 12, 13]; + let default = x4(0_usize, 1, 2, 3); + let mask = x4(1_i32, 1, 1, 1); + let expected = x4(10_usize, 11, 12, 13); + + unsafe { + let pointer = &x[0] as *const usize; + let pointers = x4( + pointer.offset(0) as *const usize, + pointer.offset(1), + pointer.offset(2), + pointer.offset(3) + ); + let result = simd_gather(default, pointers, mask); + assert_eq!(result, expected); + } + + // and again for isize + let x: [isize; 4] = [10, 11, 12, 13]; + let default = x4(0_isize, 1, 2, 3); + let expected = x4(10_isize, 11, 12, 13); + + unsafe { + let pointer = &x[0] as *const isize; + let pointers = x4( + pointer.offset(0) as *const isize, + pointer.offset(1), + pointer.offset(2), + pointer.offset(3) + ); + let result = simd_gather(default, pointers, mask); + assert_eq!(result, expected); + } + +} +