Skip to content

Commit 309bf28

Browse files
committed
Implement SIMD funnel shifts
1 parent bc5c222 commit 309bf28

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/intrinsic/simd.rs

Lines changed: 71 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,52 @@ 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+
println!("Vector type: {:?}", a_type.unqualified());
1470+
let vector_type = a_type.unqualified().dyncast_vector().expect("vector type");
1471+
let num_units = vector_type.get_num_units();
1472+
let elem_type = vector_type.get_element_type();
1473+
1474+
let (new_int_type, int_shift_val, int_mask) = if elem_type.is_compatible_with(bx.u8_type) {
1475+
(bx.u16_type, 8, u8::MAX as u64)
1476+
} else if elem_type.is_compatible_with(bx.u16_type) {
1477+
(bx.u32_type, 16, u16::MAX as u64)
1478+
} else if elem_type.is_compatible_with(bx.u32_type) {
1479+
(bx.u64_type, 32, u32::MAX as u64)
1480+
} else if elem_type.is_compatible_with(bx.u64_type) {
1481+
(bx.u128_type, 64, u64::MAX)
1482+
} else {
1483+
unimplemented!("funnel shift on {:?}", elem_type);
1484+
};
1485+
1486+
let int_mask = bx.context.new_rvalue_from_long(new_int_type, int_mask as i64);
1487+
let int_shift_val = bx.context.new_rvalue_from_int(new_int_type, int_shift_val);
1488+
let mut elements = vec![];
1489+
for i in 0..num_units {
1490+
let index = bx.context.new_rvalue_from_int(bx.int_type, i as i32);
1491+
let a_val = bx.context.new_vector_access(None, a, index).to_rvalue();
1492+
let a_val = bx.context.new_cast(None, a_val, new_int_type);
1493+
let b_val = bx.context.new_vector_access(None, b, index).to_rvalue();
1494+
let b_val = bx.context.new_cast(None, b_val, new_int_type);
1495+
let shift_val = bx.context.new_vector_access(None, shift, index).to_rvalue();
1496+
let shift_val = bx.context.new_cast(None, shift_val, new_int_type);
1497+
let mut val = a_val << int_shift_val | b_val;
1498+
if shift_left {
1499+
val = (val << shift_val) >> int_shift_val;
1500+
} else {
1501+
val = (val >> shift_val) & int_mask;
1502+
}
1503+
let val = bx.context.new_cast(None, val, elem_type);
1504+
elements.push(val);
1505+
}
1506+
bx.context.new_rvalue_from_vector(None, a_type, &elements)
1507+
}

0 commit comments

Comments
 (0)