Skip to content

Commit 9a44448

Browse files
committed
add simd_select intrinsic
1 parent 8aa27ee commit 9a44448

File tree

4 files changed

+222
-0
lines changed

4 files changed

+222
-0
lines changed

src/librustc_trans/intrinsic.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,27 @@ fn generic_simd_intrinsic<'a, 'tcx>(
11531153
return Ok(bx.extract_element(args[0].immediate(), args[1].immediate()))
11541154
}
11551155

1156+
if name == "simd_select" {
1157+
let m_elem_ty = in_elem;
1158+
let m_len = in_len;
1159+
let v_len = arg_tys[1].simd_size(tcx);
1160+
require!(m_len == v_len,
1161+
"mismatched lengths: mask length `{}` != other vector length `{}`",
1162+
m_len, v_len
1163+
);
1164+
match m_elem_ty.sty {
1165+
ty::TyInt(_) => {},
1166+
_ => {
1167+
return_error!("mask element type is `{}`, expected `i_`", m_elem_ty);
1168+
}
1169+
}
1170+
// truncate the mask to a vector of i1s
1171+
let i1 = Type::i1(bx.cx);
1172+
let i1xn = Type::vector(&i1, m_len as u64);
1173+
let m_i1s = bx.trunc(args[0].immediate(), i1xn);
1174+
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
1175+
}
1176+
11561177
macro_rules! arith_red {
11571178
($name:tt : $integer_reduce:ident, $float_reduce:ident, $ordered:expr) => {
11581179
if name == $name {

src/librustc_typeck/check/intrinsic.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ pub fn check_platform_intrinsic_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
361361
"simd_insert" => (2, vec![param(0), tcx.types.u32, param(1)], param(0)),
362362
"simd_extract" => (2, vec![param(0), tcx.types.u32], param(1)),
363363
"simd_cast" => (2, vec![param(0)], param(1)),
364+
"simd_select" => (2, vec![param(0), param(1), param(1)], param(1)),
364365
"simd_reduce_all" | "simd_reduce_any" => (1, vec![param(0)], tcx.types.bool),
365366
"simd_reduce_add_ordered" | "simd_reduce_mul_ordered"
366367
=> (2, vec![param(0), param(1)], param(1)),
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that the simd_select intrinsic produces ok-ish error
12+
// messages when misused.
13+
14+
#![feature(repr_simd, platform_intrinsics)]
15+
#![allow(non_camel_case_types)]
16+
17+
#[repr(simd)]
18+
#[derive(Copy, Clone)]
19+
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);
20+
21+
#[repr(simd)]
22+
#[derive(Copy, Clone)]
23+
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);
24+
25+
#[repr(simd)]
26+
#[derive(Copy, Clone, PartialEq)]
27+
struct b8x4(pub i8, pub i8, pub i8, pub i8);
28+
29+
#[repr(simd)]
30+
#[derive(Copy, Clone, PartialEq)]
31+
struct b8x8(pub i8, pub i8, pub i8, pub i8,
32+
pub i8, pub i8, pub i8, pub i8);
33+
34+
extern "platform-intrinsic" {
35+
fn simd_select<T, U>(x: T, a: U, b: U) -> U;
36+
}
37+
38+
fn main() {
39+
let m4 = b8x4(0, 0, 0, 0);
40+
let m8 = b8x8(0, 0, 0, 0, 0, 0, 0, 0);
41+
let x = u32x4(0, 0, 0, 0);
42+
let z = f32x4(0.0, 0.0, 0.0, 0.0);
43+
44+
unsafe {
45+
simd_select(m4, x, x);
46+
47+
simd_select(m8, x, x);
48+
//~^ ERROR mismatched lengths: mask length `8` != other vector length `4`
49+
50+
simd_select(x, x, x);
51+
//~^ ERROR mask element type is `u32`, expected `i_`
52+
53+
simd_select(z, z, z);
54+
//~^ ERROR mask element type is `f32`, expected `i_`
55+
}
56+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that the simd_select intrinsics produces correct results.
12+
13+
#![feature(repr_simd, platform_intrinsics)]
14+
#[allow(non_camel_case_types)]
15+
16+
#[repr(simd)]
17+
#[derive(Copy, Clone, PartialEq, Debug)]
18+
struct i32x4(pub i32, pub i32, pub i32, pub i32);
19+
20+
#[repr(simd)]
21+
#[derive(Copy, Clone, PartialEq, Debug)]
22+
struct u32x4(pub u32, pub u32, pub u32, pub u32);
23+
24+
#[repr(simd)]
25+
#[derive(Copy, Clone, PartialEq, Debug)]
26+
struct f32x4(pub f32, pub f32, pub f32, pub f32);
27+
28+
#[repr(simd)]
29+
#[derive(Copy, Clone, PartialEq, Debug)]
30+
struct b8x4(pub i8, pub i8, pub i8, pub i8);
31+
32+
extern "platform-intrinsic" {
33+
fn simd_select<T, U>(x: T, a: U, b: U) -> U;
34+
}
35+
36+
fn main() {
37+
let m0 = b8x4(!0, !0, !0, !0);
38+
let m1 = b8x4(0, 0, 0, 0);
39+
let m2 = b8x4(!0, !0, 0, 0);
40+
let m3 = b8x4(0, 0, !0, !0);
41+
let m4 = b8x4(!0, 0, !0, 0);
42+
43+
unsafe {
44+
let a = i32x4(1, -2, 3, 4);
45+
let b = i32x4(5, 6, -7, 8);
46+
47+
let r: i32x4 = simd_select(m0, a, b);
48+
let e = a;
49+
assert_eq!(r, e);
50+
51+
let r: i32x4 = simd_select(m1, a, b);
52+
let e = b;
53+
assert_eq!(r, e);
54+
55+
let r: i32x4 = simd_select(m2, a, b);
56+
let e = i32x4(1, -2, -7, 8);
57+
assert_eq!(r, e);
58+
59+
let r: i32x4 = simd_select(m3, a, b);
60+
let e = i32x4(5, 6, 3, 4);
61+
assert_eq!(r, e);
62+
63+
let r: i32x4 = simd_select(m4, a, b);
64+
let e = i32x4(1, 6, 3, 8);
65+
assert_eq!(r, e);
66+
}
67+
68+
unsafe {
69+
let a = u32x4(1, 2, 3, 4);
70+
let b = u32x4(5, 6, 7, 8);
71+
72+
let r: u32x4 = simd_select(m0, a, b);
73+
let e = a;
74+
assert_eq!(r, e);
75+
76+
let r: u32x4 = simd_select(m1, a, b);
77+
let e = b;
78+
assert_eq!(r, e);
79+
80+
let r: u32x4 = simd_select(m2, a, b);
81+
let e = u32x4(1, 2, 7, 8);
82+
assert_eq!(r, e);
83+
84+
let r: u32x4 = simd_select(m3, a, b);
85+
let e = u32x4(5, 6, 3, 4);
86+
assert_eq!(r, e);
87+
88+
let r: u32x4 = simd_select(m4, a, b);
89+
let e = u32x4(1, 6, 3, 8);
90+
assert_eq!(r, e);
91+
}
92+
93+
unsafe {
94+
let a = f32x4(1., 2., 3., 4.);
95+
let b = f32x4(5., 6., 7., 8.);
96+
97+
let r: f32x4 = simd_select(m0, a, b);
98+
let e = a;
99+
assert_eq!(r, e);
100+
101+
let r: f32x4 = simd_select(m1, a, b);
102+
let e = b;
103+
assert_eq!(r, e);
104+
105+
let r: f32x4 = simd_select(m2, a, b);
106+
let e = f32x4(1., 2., 7., 8.);
107+
assert_eq!(r, e);
108+
109+
let r: f32x4 = simd_select(m3, a, b);
110+
let e = f32x4(5., 6., 3., 4.);
111+
assert_eq!(r, e);
112+
113+
let r: f32x4 = simd_select(m4, a, b);
114+
let e = f32x4(1., 6., 3., 8.);
115+
assert_eq!(r, e);
116+
}
117+
118+
unsafe {
119+
let t = !0 as i8;
120+
let f = 0 as i8;
121+
let a = b8x4(t, f, t, f);
122+
let b = b8x4(f, f, f, t);
123+
124+
let r: b8x4 = simd_select(m0, a, b);
125+
let e = a;
126+
assert_eq!(r, e);
127+
128+
let r: b8x4 = simd_select(m1, a, b);
129+
let e = b;
130+
assert_eq!(r, e);
131+
132+
let r: b8x4 = simd_select(m2, a, b);
133+
let e = b8x4(t, f, f, t);
134+
assert_eq!(r, e);
135+
136+
let r: b8x4 = simd_select(m3, a, b);
137+
let e = b8x4(f, f, t, f);
138+
assert_eq!(r, e);
139+
140+
let r: b8x4 = simd_select(m4, a, b);
141+
let e = b8x4(t, f, t, t);
142+
assert_eq!(r, e);
143+
}
144+
}

0 commit comments

Comments
 (0)