Add simd_as intrinsic
This commit is contained in:
parent
d32ca64692
commit
8fae33d9b2
7 changed files with 261 additions and 173 deletions
|
@ -731,27 +731,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
fn fptoui_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
|
||||
if !self.fptoint_sat_broken_in_llvm() {
|
||||
let src_ty = self.cx.val_ty(val);
|
||||
let float_width = self.cx.float_width(src_ty);
|
||||
let int_width = self.cx.int_width(dest_ty);
|
||||
let name = format!("llvm.fptoui.sat.i{}.f{}", int_width, float_width);
|
||||
return Some(self.call_intrinsic(&name, &[val]));
|
||||
}
|
||||
|
||||
None
|
||||
self.fptoint_sat(false, val, dest_ty)
|
||||
}
|
||||
|
||||
fn fptosi_sat(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> Option<&'ll Value> {
|
||||
if !self.fptoint_sat_broken_in_llvm() {
|
||||
let src_ty = self.cx.val_ty(val);
|
||||
let float_width = self.cx.float_width(src_ty);
|
||||
let int_width = self.cx.int_width(dest_ty);
|
||||
let name = format!("llvm.fptosi.sat.i{}.f{}", int_width, float_width);
|
||||
return Some(self.call_intrinsic(&name, &[val]));
|
||||
}
|
||||
|
||||
None
|
||||
self.fptoint_sat(true, val, dest_ty)
|
||||
}
|
||||
|
||||
fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
|
@ -1455,4 +1439,43 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn fptoint_sat(
|
||||
&mut self,
|
||||
signed: bool,
|
||||
val: &'ll Value,
|
||||
dest_ty: &'ll Type,
|
||||
) -> Option<&'ll Value> {
|
||||
if !self.fptoint_sat_broken_in_llvm() {
|
||||
let src_ty = self.cx.val_ty(val);
|
||||
let (float_ty, int_ty, vector_length) = if self.cx.type_kind(src_ty) == TypeKind::Vector
|
||||
{
|
||||
assert_eq!(self.cx.vector_length(src_ty), self.cx.vector_length(dest_ty));
|
||||
(
|
||||
self.cx.element_type(src_ty),
|
||||
self.cx.element_type(dest_ty),
|
||||
Some(self.cx.vector_length(src_ty)),
|
||||
)
|
||||
} else {
|
||||
(src_ty, dest_ty, None)
|
||||
};
|
||||
let float_width = self.cx.float_width(float_ty);
|
||||
let int_width = self.cx.int_width(int_ty);
|
||||
|
||||
let instr = if signed { "fptosi" } else { "fptoui" };
|
||||
let name = if let Some(vector_length) = vector_length {
|
||||
format!(
|
||||
"llvm.{}.sat.v{}i{}.v{}f{}",
|
||||
instr, vector_length, int_width, vector_length, float_width
|
||||
)
|
||||
} else {
|
||||
format!("llvm.{}.sat.i{}.f{}", instr, int_width, float_width)
|
||||
};
|
||||
let f =
|
||||
self.declare_cfn(&name, llvm::UnnamedAddr::No, self.type_func(&[src_ty], dest_ty));
|
||||
return Some(self.call(self.type_func(&[src_ty], dest_ty), f, &[val], None));
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1689,7 +1689,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
bitwise_red!(simd_reduce_all: vector_reduce_and, true);
|
||||
bitwise_red!(simd_reduce_any: vector_reduce_or, true);
|
||||
|
||||
if name == sym::simd_cast {
|
||||
if name == sym::simd_cast || name == sym::simd_as {
|
||||
require_simd!(ret_ty, "return");
|
||||
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||
require!(
|
||||
|
@ -1761,10 +1761,10 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
});
|
||||
}
|
||||
(Style::Float, Style::Int(out_is_signed)) => {
|
||||
return Ok(if out_is_signed {
|
||||
bx.fptosi(args[0].immediate(), llret_ty)
|
||||
} else {
|
||||
bx.fptoui(args[0].immediate(), llret_ty)
|
||||
return Ok(match (out_is_signed, name == sym::simd_as) {
|
||||
(false, false) => bx.fptoui(args[0].immediate(), llret_ty),
|
||||
(true, false) => bx.fptosi(args[0].immediate(), llret_ty),
|
||||
(_, true) => bx.cast_float_to_int(out_is_signed, args[0].immediate(), llret_ty),
|
||||
});
|
||||
}
|
||||
(Style::Float, Style::Float) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue