1
Fork 0

[WIP] Real simd support

This commit is contained in:
bjorn3 2019-11-18 21:29:34 +01:00
parent c3daf6d220
commit 73fd311291
5 changed files with 62 additions and 25 deletions

View file

@ -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,
})
}

View file

@ -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),

View file

@ -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,

View file

@ -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) {

View file

@ -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,