diff --git a/compiler/compinnr.pas b/compiler/compinnr.pas index 898ab55a52..74d9deeb67 100644 --- a/compiler/compinnr.pas +++ b/compiler/compinnr.pas @@ -153,6 +153,17 @@ type in_fma_double = 134, in_fma_extended = 135, in_fma_float128 = 136, + + { the min/max intrinsics must follow the x86 sse + behaviour of min/max regarding handling + NaN: in case of a NaN the result is always the second + operand. This allows a simple translation of + if a>b then result:=a else result:=b; + statements into these intrinsics + + The min/max intrinsics are not supposed to + be exposed to the user but only + used internally by the compiler/optimizer } in_max_single = 137, in_max_double = 138, in_min_single = 139, diff --git a/compiler/x86/nx86inl.pas b/compiler/x86/nx86inl.pas index c4264060cf..b1f9d45e73 100644 --- a/compiler/x86/nx86inl.pas +++ b/compiler/x86/nx86inl.pas @@ -1479,6 +1479,14 @@ implementation end; end; + { due to min/max behaviour that it loads always the second operand (must be the else assignment) into destination if + one of the operands is a NaN, we cannot swap operands to omit a mova operation in case fastmath is off } + if not(cs_opt_fastmath in current_settings.optimizerswitches) and gotmem and (memop=1) then + begin + hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,paraarray[1].location,paraarray[1].resultdef,true); + gotmem:=false; + end; + op:=oparray[inlinenumber in [in_max_single,in_max_double],UseAVX,tfloatdef(resultdef).floattype]; location_reset(location,LOC_MMREGISTER,paraarray[1].location.size); @@ -1521,7 +1529,7 @@ implementation begin if UseAVX then emit_reg_reg_reg(op,S_NO, - paraarray[1].location.register,paraarray[2].location.register,location.register) + paraarray[2].location.register,paraarray[1].location.register,location.register) else begin hlcg.a_loadmm_reg_reg(current_asmdata.CurrAsmList,paraarray[1].resultdef,resultdef,