[WIP] Real simd support
This commit is contained in:
parent
c3daf6d220
commit
73fd311291
5 changed files with 62 additions and 25 deletions
|
@ -66,6 +66,19 @@ pub fn clif_type_from_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<types:
|
|||
}
|
||||
}
|
||||
ty::Param(_) => bug!("ty param {:?}", ty),
|
||||
_ if ty.is_simd() => {
|
||||
let (lane_type, lane_count) = crate::intrinsics::lane_type_and_count(
|
||||
tcx,
|
||||
tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap(),
|
||||
);
|
||||
let lane_type = clif_type_from_ty(tcx, lane_type.ty)?;
|
||||
let simd_type = lane_type.by(u16::try_from(lane_count).unwrap());
|
||||
if simd_type.map(|t| t.bits()) == Some(128) {
|
||||
return simd_type;
|
||||
} else {
|
||||
return None; // Not yet implemented
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ pub fn codegen_llvm_intrinsic_call<'tcx>(
|
|||
kind => unreachable!("kind {:?}", kind),
|
||||
};
|
||||
|
||||
simd_for_each_lane(fx, intrinsic, x, y, ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||
simd_pair_for_each_lane(fx, intrinsic, x, y, ret, |fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||
let res_lane = match lane_layout.ty.kind {
|
||||
ty::Float(_) => fx.bcx.ins().fcmp(flt_cc, x_lane, y_lane),
|
||||
_ => unreachable!("{:?}", lane_layout.ty),
|
||||
|
|
|
@ -144,6 +144,34 @@ pub fn lane_type_and_count<'tcx>(
|
|||
}
|
||||
|
||||
fn simd_for_each_lane<'tcx, B: Backend>(
|
||||
fx: &mut FunctionCx<'_, 'tcx, B>,
|
||||
intrinsic: &str,
|
||||
val: CValue<'tcx>,
|
||||
ret: CPlace<'tcx>,
|
||||
f: impl Fn(
|
||||
&mut FunctionCx<'_, 'tcx, B>,
|
||||
TyLayout<'tcx>,
|
||||
TyLayout<'tcx>,
|
||||
Value,
|
||||
) -> CValue<'tcx>,
|
||||
) {
|
||||
let layout = val.layout();
|
||||
|
||||
let (lane_layout, lane_count) = lane_type_and_count(fx.tcx, layout);
|
||||
let (ret_lane_layout, ret_lane_count) = lane_type_and_count(fx.tcx, ret.layout());
|
||||
assert_eq!(lane_count, ret_lane_count);
|
||||
|
||||
for lane_idx in 0..lane_count {
|
||||
let lane_idx = mir::Field::new(lane_idx.try_into().unwrap());
|
||||
let lane = val.value_field(fx, lane_idx).load_scalar(fx);
|
||||
|
||||
let res_lane = f(fx, lane_layout, ret_lane_layout, lane);
|
||||
|
||||
ret.place_field(fx, lane_idx).write_cvalue(fx, res_lane);
|
||||
}
|
||||
}
|
||||
|
||||
fn simd_pair_for_each_lane<'tcx, B: Backend>(
|
||||
fx: &mut FunctionCx<'_, 'tcx, B>,
|
||||
intrinsic: &str,
|
||||
x: CValue<'tcx>,
|
||||
|
@ -204,7 +232,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
|
|||
|
||||
macro simd_cmp {
|
||||
($fx:expr, $intrinsic:expr, $cc:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane(
|
||||
simd_pair_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
|
@ -220,7 +248,7 @@ macro simd_cmp {
|
|||
);
|
||||
},
|
||||
($fx:expr, $intrinsic:expr, $cc_u:ident|$cc_s:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane(
|
||||
simd_pair_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
|
@ -240,7 +268,7 @@ macro simd_cmp {
|
|||
|
||||
macro simd_int_binop {
|
||||
($fx:expr, $intrinsic:expr, $op:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane(
|
||||
simd_pair_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
|
@ -256,7 +284,7 @@ macro simd_int_binop {
|
|||
);
|
||||
},
|
||||
($fx:expr, $intrinsic:expr, $op_u:ident|$op_s:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane(
|
||||
simd_pair_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
|
@ -276,7 +304,7 @@ macro simd_int_binop {
|
|||
|
||||
macro simd_int_flt_binop {
|
||||
($fx:expr, $intrinsic:expr, $op:ident|$op_f:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane(
|
||||
simd_pair_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
|
@ -293,7 +321,7 @@ macro simd_int_flt_binop {
|
|||
);
|
||||
},
|
||||
($fx:expr, $intrinsic:expr, $op_u:ident|$op_s:ident|$op_f:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||
simd_for_each_lane(
|
||||
simd_pair_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
|
@ -313,7 +341,7 @@ macro simd_int_flt_binop {
|
|||
}
|
||||
|
||||
macro simd_flt_binop($fx:expr, $intrinsic:expr, $op:ident($x:ident, $y:ident) -> $ret:ident) {
|
||||
simd_for_each_lane(
|
||||
simd_pair_for_each_lane(
|
||||
$fx,
|
||||
$intrinsic,
|
||||
$x,
|
||||
|
|
|
@ -21,22 +21,15 @@ pub fn codegen_simd_intrinsic_call<'tcx>(
|
|||
};
|
||||
|
||||
simd_cast, (c a) {
|
||||
let (lane_layout, lane_count) = lane_type_and_count(fx.tcx, a.layout());
|
||||
let (ret_lane_layout, ret_lane_count) = lane_type_and_count(fx.tcx, ret.layout());
|
||||
assert_eq!(lane_count, ret_lane_count);
|
||||
simd_for_each_lane(fx, intrinsic, a, ret, |fx, lane_layout, ret_lane_layout, lane| {
|
||||
let ret_lane_ty = fx.clif_type(ret_lane_layout.ty).unwrap();
|
||||
|
||||
let ret_lane_ty = fx.clif_type(ret_lane_layout.ty).unwrap();
|
||||
let from_signed = type_sign(lane_layout.ty);
|
||||
let to_signed = type_sign(ret_lane_layout.ty);
|
||||
|
||||
let from_signed = type_sign(lane_layout.ty);
|
||||
let to_signed = type_sign(ret_lane_layout.ty);
|
||||
|
||||
for lane in 0..lane_count {
|
||||
let lane = mir::Field::new(lane.try_into().unwrap());
|
||||
|
||||
let a_lane = a.value_field(fx, lane).load_scalar(fx);
|
||||
let res = clif_int_or_float_cast(fx, a_lane, from_signed, ret_lane_ty, to_signed);
|
||||
ret.place_field(fx, lane).write_cvalue(fx, CValue::by_val(res, ret_lane_layout));
|
||||
}
|
||||
let ret_lane = clif_int_or_float_cast(fx, lane, from_signed, ret_lane_ty, to_signed);
|
||||
CValue::by_val(ret_lane, ret_lane_layout)
|
||||
});
|
||||
};
|
||||
|
||||
simd_eq, (c x, c y) {
|
||||
|
|
|
@ -122,11 +122,14 @@ impl<'tcx> CValue<'tcx> {
|
|||
let layout = self.1;
|
||||
match self.0 {
|
||||
CValueInner::ByRef(ptr) => {
|
||||
let scalar = match layout.abi {
|
||||
layout::Abi::Scalar(ref scalar) => scalar.clone(),
|
||||
let clif_ty = match layout.abi {
|
||||
layout::Abi::Scalar(ref scalar) => scalar_to_clif_type(fx.tcx, scalar.clone()),
|
||||
layout::Abi::Vector { ref element, count } => {
|
||||
scalar_to_clif_type(fx.tcx, element.clone())
|
||||
.by(u16::try_from(count).unwrap()).unwrap()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let clif_ty = scalar_to_clif_type(fx.tcx, scalar);
|
||||
ptr.load(fx, clif_ty, MemFlags::new())
|
||||
}
|
||||
CValueInner::ByVal(value) => value,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue