Skip to content

Commit cc7c9be

Browse files
committed
implement simd_bswap intrinsic
Implements lane-local byte swapping through vector shuffles. While this is more setup than non-vector shuffles, this implementation can shuffle multiple integers concurrently. Signed-off-by: Andy Sadler <[email protected]>
1 parent c6bc7ec commit cc7c9be

File tree

1 file changed

+54
-0
lines changed

1 file changed

+54
-0
lines changed

src/intrinsic/simd.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::iter::FromIterator;
2+
13
use gccjit::ToRValue;
24
use gccjit::{BinaryOp, RValue, Type};
35
#[cfg(feature = "master")]
@@ -156,6 +158,58 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
156158
return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op));
157159
}
158160

161+
if name == sym::simd_bswap {
162+
let vector = args[0].immediate();
163+
let ret = match in_elem.kind() {
164+
ty::Int(i) if i.bit_width() == Some(8) => vector,
165+
ty::Uint(i) if i.bit_width() == Some(8) => vector,
166+
ty::Int(_) | ty::Uint(_) => {
167+
let v_type = vector.get_type();
168+
let vector_type = v_type.unqualified().dyncast_vector().expect("vector type");
169+
let elem_type = vector_type.get_element_type();
170+
let elem_size_bytes = elem_type.get_size();
171+
let type_size_bytes = elem_size_bytes as u64 * in_len;
172+
173+
let shuffle_indices = Vec::from_iter(0..type_size_bytes);
174+
let byte_vector_type = bx.context.new_vector_type(bx.type_u8(), type_size_bytes);
175+
let byte_vector = bx.context.new_bitcast(None, args[0].immediate(), byte_vector_type);
176+
177+
#[cfg(not(feature = "master"))]
178+
let shuffled = {
179+
let new_elements: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _)
180+
.flat_map(|x| x.iter().rev())
181+
.map(|&i| {
182+
let index = bx.context.new_rvalue_from_long(bx.u64_type, i as _);
183+
bx.extract_element(byte_vector, index)
184+
})
185+
.collect();
186+
187+
bx.context.new_rvalue_from_vector(None, byte_vector_type, &new_elements)
188+
};
189+
#[cfg(feature = "master")]
190+
let shuffled = {
191+
let indices: Vec<_> = shuffle_indices.chunks_exact(elem_size_bytes as _)
192+
.flat_map(|x| x.iter().rev())
193+
.map(|&i| bx.context.new_rvalue_from_int(bx.u8_type, i as _))
194+
.collect();
195+
196+
let mask = bx.context.new_rvalue_from_vector(None, byte_vector_type, &indices);
197+
bx.context.new_rvalue_vector_perm(None, byte_vector, byte_vector, mask)
198+
};
199+
bx.context.new_bitcast(None, shuffled, v_type)
200+
}
201+
_ => {
202+
return_error!(InvalidMonomorphization::UnsupportedOperation {
203+
span,
204+
name,
205+
in_ty,
206+
in_elem,
207+
});
208+
}
209+
};
210+
return Ok(ret);
211+
}
212+
159213
if name == sym::simd_shuffle {
160214
// Make sure this is actually an array, since typeck only checks the length-suffixed
161215
// version of this intrinsic.

0 commit comments

Comments
 (0)