Merge commit 'f2cdd4a78d89c009342197cf5844a21f8aa813df' into sync_cg_clif-2022-04-22

This commit is contained in:
bjorn3
2022-04-22 21:11:38 +02:00
21 changed files with 189 additions and 142 deletions

View File

@@ -1019,39 +1019,23 @@ fn codegen_regular_intrinsic_call<'tcx>(
ret.write_cvalue(fx, old);
};
// In Rust floating point min and max don't propagate NaN. In Cranelift they do however.
// For this reason it is necessary to use `a.is_nan() ? b : (a >= b ? b : a)` for `minnumf*`
// and `a.is_nan() ? b : (a <= b ? b : a)` for `maxnumf*`. NaN checks are done by comparing
// a float against itself. Only in case of NaN is it not equal to itself.
minnumf32, (v a, v b) {
let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
let temp = fx.bcx.ins().select(a_ge_b, b, a);
let val = fx.bcx.ins().select(a_is_nan, b, temp);
let val = crate::num::codegen_float_min(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
ret.write_cvalue(fx, val);
};
minnumf64, (v a, v b) {
let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
let a_ge_b = fx.bcx.ins().fcmp(FloatCC::GreaterThanOrEqual, a, b);
let temp = fx.bcx.ins().select(a_ge_b, b, a);
let val = fx.bcx.ins().select(a_is_nan, b, temp);
let val = crate::num::codegen_float_min(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
ret.write_cvalue(fx, val);
};
maxnumf32, (v a, v b) {
let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
let temp = fx.bcx.ins().select(a_le_b, b, a);
let val = fx.bcx.ins().select(a_is_nan, b, temp);
let val = crate::num::codegen_float_max(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f32));
ret.write_cvalue(fx, val);
};
maxnumf64, (v a, v b) {
let a_is_nan = fx.bcx.ins().fcmp(FloatCC::NotEqual, a, a);
let a_le_b = fx.bcx.ins().fcmp(FloatCC::LessThanOrEqual, a, b);
let temp = fx.bcx.ins().select(a_le_b, b, a);
let val = fx.bcx.ins().select(a_is_nan, b, temp);
let val = crate::num::codegen_float_max(fx, a, b);
let val = CValue::by_val(val, fx.layout_of(fx.tcx.types.f64));
ret.write_cvalue(fx, val);
};

View File

@@ -322,20 +322,21 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
}
assert_eq!(a.layout(), b.layout());
assert_eq!(a.layout(), c.layout());
let layout = a.layout();
assert_eq!(a.layout(), ret.layout());
let (lane_count, _lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx);
assert_eq!(lane_count, ret_lane_count);
let ret_lane_layout = fx.layout_of(ret_lane_ty);
let layout = a.layout();
let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx);
for lane in 0..lane_count {
let a_lane = a.value_lane(fx, lane).load_scalar(fx);
let b_lane = b.value_lane(fx, lane).load_scalar(fx);
let c_lane = c.value_lane(fx, lane).load_scalar(fx);
let a_lane = a.value_lane(fx, lane);
let b_lane = b.value_lane(fx, lane);
let c_lane = c.value_lane(fx, lane);
let mul_lane = fx.bcx.ins().fmul(a_lane, b_lane);
let res_lane = CValue::by_val(fx.bcx.ins().fadd(mul_lane, c_lane), ret_lane_layout);
let res_lane = match lane_ty.kind() {
ty::Float(FloatTy::F32) => fx.easy_call("fmaf", &[a_lane, b_lane, c_lane], lane_ty),
ty::Float(FloatTy::F64) => fx.easy_call("fma", &[a_lane, b_lane, c_lane], lane_ty),
_ => unreachable!(),
};
ret.place_lane(fx, lane).write_cvalue(fx, res_lane);
}
@@ -354,8 +355,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
_ => unreachable!("{:?}", lane_ty),
}
match intrinsic {
sym::simd_fmin => fx.bcx.ins().fmin(x_lane, y_lane),
sym::simd_fmax => fx.bcx.ins().fmax(x_lane, y_lane),
sym::simd_fmin => crate::num::codegen_float_min(fx, x_lane, y_lane),
sym::simd_fmax => crate::num::codegen_float_max(fx, x_lane, y_lane),
_ => unreachable!(),
}
});
@@ -495,7 +496,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let lt = match ty.kind() {
ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedLessThan, a, b),
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedLessThan, a, b),
ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::LessThan, a, b),
ty::Float(_) => return crate::num::codegen_float_min(fx, a, b),
_ => unreachable!(),
};
fx.bcx.ins().select(lt, a, b)
@@ -512,7 +513,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let gt = match ty.kind() {
ty::Int(_) => fx.bcx.ins().icmp(IntCC::SignedGreaterThan, a, b),
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::UnsignedGreaterThan, a, b),
ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::GreaterThan, a, b),
ty::Float(_) => return crate::num::codegen_float_max(fx, a, b),
_ => unreachable!(),
};
fx.bcx.ins().select(gt, a, b)