Skip to content

Commit 040fde4

Browse files
Ensure that negation of floating-point values is correctly handled (#105629)
* Ensure that negation of floating-point values is correctly handled * Fix paren in test * Ensure the managed fallback for negate handles float properly
1 parent 175cd64 commit 040fde4

File tree

8 files changed

+140
-17
lines changed

8 files changed

+140
-17
lines changed

src/coreclr/jit/simd.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,11 @@ TBase EvaluateUnaryScalarSpecialized(genTreeOps oper, TBase arg0)
368368
{
369369
switch (oper)
370370
{
371+
case GT_NEG:
372+
{
373+
return static_cast<TBase>(0) - arg0;
374+
}
375+
371376
case GT_NOT:
372377
{
373378
return ~arg0;
@@ -399,6 +404,11 @@ TBase EvaluateUnaryScalarSpecialized(genTreeOps oper, TBase arg0)
399404
template <>
400405
inline float EvaluateUnaryScalarSpecialized<float>(genTreeOps oper, float arg0)
401406
{
407+
if (oper == GT_NEG)
408+
{
409+
return -arg0;
410+
}
411+
402412
uint32_t arg0Bits = BitOperations::SingleToUInt32Bits(arg0);
403413
uint32_t resultBits = EvaluateUnaryScalarSpecialized<uint32_t>(oper, arg0Bits);
404414
return BitOperations::UInt32BitsToSingle(resultBits);
@@ -407,6 +417,11 @@ inline float EvaluateUnaryScalarSpecialized<float>(genTreeOps oper, float arg0)
407417
template <>
408418
inline double EvaluateUnaryScalarSpecialized<double>(genTreeOps oper, double arg0)
409419
{
420+
if (oper == GT_NEG)
421+
{
422+
return -arg0;
423+
}
424+
410425
uint64_t arg0Bits = BitOperations::DoubleToUInt64Bits(arg0);
411426
uint64_t resultBits = EvaluateUnaryScalarSpecialized<uint64_t>(oper, arg0Bits);
412427
return BitOperations::UInt64BitsToDouble(resultBits);
@@ -415,18 +430,7 @@ inline double EvaluateUnaryScalarSpecialized<double>(genTreeOps oper, double arg
415430
template <typename TBase>
416431
TBase EvaluateUnaryScalar(genTreeOps oper, TBase arg0)
417432
{
418-
switch (oper)
419-
{
420-
case GT_NEG:
421-
{
422-
return static_cast<TBase>(0) - arg0;
423-
}
424-
425-
default:
426-
{
427-
return EvaluateUnaryScalarSpecialized<TBase>(oper, arg0);
428-
}
429-
}
433+
return EvaluateUnaryScalarSpecialized<TBase>(oper, arg0);
430434
}
431435

432436
#if defined(FEATURE_MASKED_HW_INTRINSICS)

src/libraries/System.Private.CoreLib/src/System/Numerics/Vector_1.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,22 @@ public static Vector<T> operator >>(Vector<T> value, int shiftCount)
576576
/// <param name="value">The vector to negate.</param>
577577
/// <returns>A vector whose elements are the unary negation of the corresponding elements in <paramref name="value" />.</returns>
578578
[Intrinsic]
579-
public static Vector<T> operator -(Vector<T> value) => Zero - value;
579+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
580+
public static Vector<T> operator -(Vector<T> value)
581+
{
582+
if (typeof(T) == typeof(float))
583+
{
584+
return value ^ Vector.Create(-0.0f).As<float, T>();
585+
}
586+
else if (typeof(T) == typeof(double))
587+
{
588+
return value ^ Vector.Create(-0.0).As<double, T>();
589+
}
590+
else
591+
{
592+
return Zero - value;
593+
}
594+
}
580595

581596
/// <summary>Returns a given vector unchanged.</summary>
582597
/// <param name="value">The vector.</param>

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector128_1.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,22 @@ public static Vector128<T> operator >>(Vector128<T> value, int shiftCount)
337337
/// <returns>A vector whose elements are the unary negation of the corresponding elements in <paramref name="vector" />.</returns>
338338
/// <exception cref="NotSupportedException">The type of the vector (<typeparamref name="T" />) is not supported.</exception>
339339
[Intrinsic]
340-
public static Vector128<T> operator -(Vector128<T> vector) => Zero - vector;
340+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
341+
public static Vector128<T> operator -(Vector128<T> vector)
342+
{
343+
if (typeof(T) == typeof(float))
344+
{
345+
return vector ^ Vector128.Create(-0.0f).As<float, T>();
346+
}
347+
else if (typeof(T) == typeof(double))
348+
{
349+
return vector ^ Vector128.Create(-0.0).As<double, T>();
350+
}
351+
else
352+
{
353+
return Zero - vector;
354+
}
355+
}
341356

342357
/// <summary>Returns a given vector unchanged.</summary>
343358
/// <param name="value">The vector.</param>

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector256_1.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,22 @@ public static Vector256<T> operator >>(Vector256<T> value, int shiftCount)
335335
/// <returns>A vector whose elements are the unary negation of the corresponding elements in <paramref name="vector" />.</returns>
336336
/// <exception cref="NotSupportedException">The type of the vector (<typeparamref name="T" />) is not supported.</exception>
337337
[Intrinsic]
338-
public static Vector256<T> operator -(Vector256<T> vector) => Zero - vector;
338+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
339+
public static Vector256<T> operator -(Vector256<T> vector)
340+
{
341+
if (typeof(T) == typeof(float))
342+
{
343+
return vector ^ Vector256.Create(-0.0f).As<float, T>();
344+
}
345+
else if (typeof(T) == typeof(double))
346+
{
347+
return vector ^ Vector256.Create(-0.0).As<double, T>();
348+
}
349+
else
350+
{
351+
return Zero - vector;
352+
}
353+
}
339354

340355
/// <summary>Returns a given vector unchanged.</summary>
341356
/// <param name="value">The vector.</param>

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector512_1.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,22 @@ public static Vector512<T> operator >>(Vector512<T> value, int shiftCount)
335335
/// <returns>A vector whose elements are the unary negation of the corresponding elements in <paramref name="vector" />.</returns>
336336
/// <exception cref="NotSupportedException">The type of the vector (<typeparamref name="T" />) is not supported.</exception>
337337
[Intrinsic]
338-
public static Vector512<T> operator -(Vector512<T> vector) => Zero - vector;
338+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
339+
public static Vector512<T> operator -(Vector512<T> vector)
340+
{
341+
if (typeof(T) == typeof(float))
342+
{
343+
return vector ^ Vector512.Create(-0.0f).As<float, T>();
344+
}
345+
else if (typeof(T) == typeof(double))
346+
{
347+
return vector ^ Vector512.Create(-0.0).As<double, T>();
348+
}
349+
else
350+
{
351+
return Zero - vector;
352+
}
353+
}
339354

340355
/// <summary>Returns a given vector unchanged.</summary>
341356
/// <param name="value">The vector.</param>

src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/Vector64_1.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,22 @@ public static Vector64<T> operator >>(Vector64<T> value, int shiftCount)
389389
/// <returns>A vector whose elements are the unary negation of the corresponding elements in <paramref name="vector" />.</returns>
390390
/// <exception cref="NotSupportedException">The type of the vector (<typeparamref name="T" />) is not supported.</exception>
391391
[Intrinsic]
392-
public static Vector64<T> operator -(Vector64<T> vector) => Zero - vector;
392+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
393+
public static Vector64<T> operator -(Vector64<T> vector)
394+
{
395+
if (typeof(T) == typeof(float))
396+
{
397+
return vector ^ Vector64.Create(-0.0f).As<float, T>();
398+
}
399+
else if (typeof(T) == typeof(double))
400+
{
401+
return vector ^ Vector64.Create(-0.0).As<double, T>();
402+
}
403+
else
404+
{
405+
return Zero - vector;
406+
}
407+
}
393408

394409
/// <summary>Returns a given vector unchanged.</summary>
395410
/// <param name="value">The vector.</param>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
using System.Numerics;
7+
using System.Runtime.Intrinsics;
8+
using System.Runtime.Intrinsics.Arm;
9+
using Xunit;
10+
11+
// Run on Arm64 Linux
12+
// Seed: 10489942769529190437-vectort,vector64,vector128,armadvsimd,armadvsimdarm64,armaes,armarmbase,armarmbasearm64,armcrc32,armcrc32arm64,armdp,armrdm,armrdmarm64,armsha1,armsha256
13+
// Reduced from 58.9 KiB to 0.4 KiB in 00:00:28
14+
// Debug: Outputs [9223372036854775808, 9223372036854775808]
15+
// Release: Outputs [0, 0]
16+
17+
public class Runtime_105627
18+
{
19+
public static Vector128<double> s_9;
20+
21+
[Fact]
22+
public static void TestEntyPoint()
23+
{
24+
var vr1 = Vector128.CreateScalar(0d);
25+
26+
if (AdvSimd.IsSupported)
27+
{
28+
s_9 = AdvSimd.Arm64.Negate(vr1);
29+
}
30+
else
31+
{
32+
s_9 = -vr1;
33+
}
34+
Assert.Equal(Vector128.Create<ulong>(0x80000000_00000000UL), s_9.AsUInt64());
35+
}
36+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Optimize>True</Optimize>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="$(MSBuildProjectName).cs" />
7+
</ItemGroup>
8+
</Project>

0 commit comments

Comments
 (0)