Skip to content

Commit e3a6469

Browse files
committed
Implement SIMD funnel shifts
1 parent bc5c222 commit e3a6469

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

src/intrinsic/simd.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
206206
);
207207
}
208208

209+
#[cfg(feature = "master")]
210+
if name == sym::simd_funnel_shl {
211+
return Ok(simd_funnel_shift(
212+
bx,
213+
args[0].immediate(),
214+
args[1].immediate(),
215+
args[2].immediate(),
216+
true,
217+
));
218+
}
219+
220+
#[cfg(feature = "master")]
221+
if name == sym::simd_funnel_shr {
222+
return Ok(simd_funnel_shift(
223+
bx,
224+
args[0].immediate(),
225+
args[1].immediate(),
226+
args[2].immediate(),
227+
false,
228+
));
229+
}
230+
209231
if name == sym::simd_bswap {
210232
return Ok(simd_bswap(bx, args[0].immediate()));
211233
}
@@ -1434,3 +1456,59 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
14341456

14351457
unimplemented!("simd {}", name);
14361458
}
1459+
1460+
#[cfg(feature = "master")]
1461+
fn simd_funnel_shift<'a, 'gcc, 'tcx>(
1462+
bx: &mut Builder<'a, 'gcc, 'tcx>,
1463+
a: RValue<'gcc>,
1464+
b: RValue<'gcc>,
1465+
shift: RValue<'gcc>,
1466+
shift_left: bool,
1467+
) -> RValue<'gcc> {
1468+
let a_type = a.get_type();
1469+
let vector_type = a_type.unqualified().dyncast_vector().expect("vector type");
1470+
let num_units = vector_type.get_num_units();
1471+
let elem_type = vector_type.get_element_type();
1472+
1473+
let (new_int_type, int_shift_val, int_mask) = if elem_type.is_compatible_with(bx.u8_type) {
1474+
(bx.u16_type, 8, u8::MAX as u64)
1475+
} else if elem_type.is_compatible_with(bx.u16_type) {
1476+
(bx.u32_type, 16, u16::MAX as u64)
1477+
} else if elem_type.is_compatible_with(bx.u32_type) {
1478+
(bx.u64_type, 32, u32::MAX as u64)
1479+
} else if elem_type.is_compatible_with(bx.u64_type) {
1480+
(bx.u128_type, 64, u64::MAX)
1481+
} else if elem_type.is_compatible_with(bx.i8_type) {
1482+
(bx.i16_type, 8, u8::MAX as u64)
1483+
} else if elem_type.is_compatible_with(bx.i16_type) {
1484+
(bx.i32_type, 16, u16::MAX as u64)
1485+
} else if elem_type.is_compatible_with(bx.i32_type) {
1486+
(bx.i64_type, 32, u32::MAX as u64)
1487+
} else if elem_type.is_compatible_with(bx.i64_type) {
1488+
(bx.i128_type, 64, u64::MAX)
1489+
} else {
1490+
unimplemented!("funnel shift on {:?}", elem_type);
1491+
};
1492+
1493+
let int_mask = bx.context.new_rvalue_from_long(new_int_type, int_mask as i64);
1494+
let int_shift_val = bx.context.new_rvalue_from_int(new_int_type, int_shift_val);
1495+
let mut elements = vec![];
1496+
for i in 0..num_units {
1497+
let index = bx.context.new_rvalue_from_int(bx.int_type, i as i32);
1498+
let a_val = bx.context.new_vector_access(None, a, index).to_rvalue();
1499+
let a_val = bx.context.new_cast(None, a_val, new_int_type);
1500+
let b_val = bx.context.new_vector_access(None, b, index).to_rvalue();
1501+
let b_val = bx.context.new_cast(None, b_val, new_int_type);
1502+
let shift_val = bx.context.new_vector_access(None, shift, index).to_rvalue();
1503+
let shift_val = bx.context.new_cast(None, shift_val, new_int_type);
1504+
let mut val = a_val << int_shift_val | b_val;
1505+
if shift_left {
1506+
val = (val << shift_val) >> int_shift_val;
1507+
} else {
1508+
val = (val >> shift_val) & int_mask;
1509+
}
1510+
let val = bx.context.new_cast(None, val, elem_type);
1511+
elements.push(val);
1512+
}
1513+
bx.context.new_rvalue_from_vector(None, a_type, &elements)
1514+
}

0 commit comments

Comments
 (0)