Add Unsafe_IgnoreStandardFPCRValue optimization

This commit is contained in:
MerryMage 2021-06-08 17:26:45 +01:00
parent c157dfcc4c
commit c1d5a7977e
3 changed files with 6 additions and 3 deletions

View file

@ -1681,7 +1681,7 @@ void EmitX64::EmitFPFixedS32ToSingle(EmitContext& ctx, IR::Inst* inst) {
const size_t fbits = args[1].GetImmediateU8(); const size_t fbits = args[1].GetImmediateU8();
const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8()); const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
if (rounding_mode == ctx.FPCR().RMode()) { if (rounding_mode == ctx.FPCR().RMode() || ctx.HasOptimization(OptimizationFlag::Unsafe_IgnoreStandardFPCRValue)) {
code.cvtsi2ss(result, from); code.cvtsi2ss(result, from);
} else { } else {
ASSERT(rounding_mode == FP::RoundingMode::ToNearest_TieEven); ASSERT(rounding_mode == FP::RoundingMode::ToNearest_TieEven);
@ -1717,7 +1717,7 @@ void EmitX64::EmitFPFixedU32ToSingle(EmitContext& ctx, IR::Inst* inst) {
} }
}; };
if (rounding_mode == ctx.FPCR().RMode()) { if (rounding_mode == ctx.FPCR().RMode() || ctx.HasOptimization(OptimizationFlag::Unsafe_IgnoreStandardFPCRValue)) {
op(); op();
} else { } else {
ASSERT(rounding_mode == FP::RoundingMode::ToNearest_TieEven); ASSERT(rounding_mode == FP::RoundingMode::ToNearest_TieEven);

View file

@ -58,7 +58,7 @@ template<typename Lambda>
void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, Lambda lambda) { void MaybeStandardFPSCRValue(BlockOfCode& code, EmitContext& ctx, bool fpcr_controlled, Lambda lambda) {
const bool switch_mxcsr = ctx.FPCR(fpcr_controlled) != ctx.FPCR(); const bool switch_mxcsr = ctx.FPCR(fpcr_controlled) != ctx.FPCR();
if (switch_mxcsr) { if (switch_mxcsr && !ctx.HasOptimization(OptimizationFlag::Unsafe_IgnoreStandardFPCRValue)) {
code.EnterStandardASIMD(); code.EnterStandardASIMD();
lambda(); lambda();
code.LeaveStandardASIMD(); code.LeaveStandardASIMD();

View file

@ -42,6 +42,9 @@ enum class OptimizationFlag : std::uint32_t {
/// This is an UNSAFE optimization that causes floating-point instructions to not produce correct NaNs. /// This is an UNSAFE optimization that causes floating-point instructions to not produce correct NaNs.
/// This may also result in inaccurate results when instructions are given certain special values. /// This may also result in inaccurate results when instructions are given certain special values.
Unsafe_InaccurateNaN = 0x00040000, Unsafe_InaccurateNaN = 0x00040000,
/// This is an UNSAFE optimization that causes ASIMD floating-point instructions to be run with incorrect
/// rounding modes. This may result in inaccurate results with all floating-point ASIMD instructions.
Unsafe_IgnoreStandardFPCRValue = 0x00080000,
}; };
constexpr OptimizationFlag no_optimizations = static_cast<OptimizationFlag>(0); constexpr OptimizationFlag no_optimizations = static_cast<OptimizationFlag>(0);