SSE and SSE2 CompareGreaterThan methods properly handle NaN inputs

The following System.Runtime.Intrinsics.X86.Sse and System.Runtime.Intrinsics.X86.Sse2 methods have been fixed to properly handle NaN inputs and match the hardware behavior of the equivalent methods in the System.Runtime.Intrinsics.X86.Avx class:

  • CompareGreaterThan
  • CompareGreaterThanOrEqual
  • CompareNotGreaterThan
  • CompareNotGreaterThanOrEqual
  • CompareScalarGreaterThan
  • CompareScalarGreaterThanOrEqual
  • CompareScalarNotGreaterThan
  • CompareScalarNotGreaterThanOrEqual

Change description

Previously, NaN inputs to the listed Sse and Sse2 methods returned an incorrect result. The result also differed from the result generated by the corresponding method in the Avx class.

Starting in .NET 5, these methods correctly handle NaN inputs and return the same results as the corresponding methods in the Avx class.

The Streaming SIMD Extensions (SSE) and Streaming SIMD Extensions 2 (SSE2) industry standard architectures (ISAs) don't provide direct hardware support for these comparison methods, so they're implemented in software. Previously, the methods were improperly implemented, and they incorrectly handled NaN inputs. For code ported from native, the incorrect behavior may introduce bugs. For a 256-bit code path, the methods can also produce different results to the equivalent methods in the Avx class.

As an example of how the methods were previously incorrect, you can implement CompareNotGreaterThan(x,y) as CompareLessThanOrEqual(x,y) for regular integers. However, for NaN inputs, that logic computes the wrong result. Instead, using CompareNotLessThan(y,x) compares the numbers correctly and takes NaN inputs into consideration.

Version introduced

5.0

  • If the previous behavior was a bug, no change is required.

  • If the previous behavior was desired, you can maintain that behavior by changing the relevant invocation as follows:

    • CompareGreaterThan(x,y) -> CompareNotLessThanOrEqual(x,y)
    • CompareGreaterThanOrEqual(x,y) -> CompareNotLessThan(x,y)
    • CompareNotGreaterThan(x,y) -> CompareLessThanOrEqual(x,y)
    • CompareNotGreaterThanOrEqual(x,y) -> CompareLessThan(x,y)
    • CompareScalarGreaterThan(x,y) -> CompareScalarNotLessThanOrEqual(x,y)
    • CompareScalarGreaterThanOrEqual(x,y) -> CompareScalarNotLessThan(x,y)
    • CompareScalarNotGreaterThan(x,y) -> CompareScalarLessThanOrEqual(x,y)
    • CompareScalarNotGreaterThanOrEqual(x,y) -> CompareScalarLessThan(x,y)

Affected APIs