diff --git a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs index d8f9646f54e44b..3fce828ba35bf0 100644 --- a/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs +++ b/src/tests/JIT/HardwareIntrinsics/Arm/Shared/Helpers.cs @@ -1822,18 +1822,18 @@ private static (short val, bool ovf) MultiplyDoublingOvf(sbyte op1, sbyte op2, b short product = (short)((short)op1 * (short)op2); bool dblOvf; - (product, dblOvf) = AddOvf(product, product); + dblOvf = TryAddSigned(product, product, out product); bool addOvf; short accum; if (subOp) { - (accum, addOvf) = SubtractOvf(op3, product); + addOvf = TrySubSigned(op3, product, out accum); } else { - (accum, addOvf) = AddOvf(op3, product); + addOvf = TryAddSigned(op3, product, out accum); } short roundConst = 0; @@ -1846,7 +1846,7 @@ private static (short val, bool ovf) MultiplyDoublingOvf(sbyte op1, sbyte op2, b bool rndOvf; short result; - (result, rndOvf) = AddOvf(accum, roundConst); + rndOvf = TryAddSigned(accum, roundConst, out result); return (result, addOvf ^ rndOvf ^ dblOvf); } @@ -2183,18 +2183,18 @@ private static (int val, bool ovf) MultiplyDoublingOvf(short op1, short op2, boo int product = (int)((int)op1 * (int)op2); bool dblOvf; - (product, dblOvf) = AddOvf(product, product); + dblOvf = TryAddSigned(product, product, out product); bool addOvf; int accum; if (subOp) { - (accum, addOvf) = SubtractOvf(op3, product); + addOvf = TrySubSigned(op3, product, out accum); } else { - (accum, addOvf) = AddOvf(op3, product); + addOvf = TryAddSigned(op3, product, out accum); } int roundConst = 0; @@ -2207,7 +2207,7 @@ private static (int val, bool ovf) MultiplyDoublingOvf(short op1, short op2, boo bool rndOvf; int result; - (result, rndOvf) = AddOvf(accum, roundConst); + rndOvf = TryAddSigned(accum, roundConst, out result); return (result, addOvf ^ rndOvf ^ dblOvf); } @@ -2567,18 +2567,18 @@ private static (long val, bool ovf) MultiplyDoublingOvf(int op1, int op2, bool r long product = (long)((long)op1 * (long)op2); bool dblOvf; - (product, dblOvf) = AddOvf(product, product); + dblOvf = TryAddSigned(product, product, out product); bool addOvf; long accum; if (subOp) { - (accum, addOvf) = SubtractOvf(op3, product); + addOvf = TrySubSigned(op3, product, out accum); } else { - (accum, addOvf) = AddOvf(op3, product); + addOvf = TryAddSigned(op3, product, out accum); } long roundConst = 0; @@ -2591,7 +2591,7 @@ private static (long val, bool ovf) MultiplyDoublingOvf(int op1, int op2, bool r bool rndOvf; long result; - (result, rndOvf) = AddOvf(accum, roundConst); + rndOvf = TryAddSigned(accum, roundConst, out result); return (result, addOvf ^ rndOvf ^ dblOvf); } @@ -2966,7 +2966,7 @@ private static sbyte SignedShift(sbyte op1, sbyte op2, bool rounding = false, bo bool addOvf; - (result, addOvf) = AddOvf(op1, rndCns); + addOvf = TryAddSigned(op1, rndCns, out result); if (addOvf) { @@ -3070,7 +3070,8 @@ private static byte UnsignedShift(byte op1, sbyte op2, bool rounding = false, bo } } - (byte result, bool addOvf) = AddOvf(op1, rndCns); + byte result; + bool addOvf = TryAddUnsigned(op1, rndCns, out result); bool shiftOvf; @@ -3095,122 +3096,98 @@ private static byte UnsignedShift(byte op1, sbyte op2, bool rounding = false, bo private static sbyte UnsignedShift(sbyte op1, sbyte op2, bool rounding = false, bool saturating = false) => (sbyte)UnsignedShift((byte)op1, op2, rounding, saturating); - private static (sbyte val, bool ovf) AddOvf(sbyte op1, sbyte op2) + private static bool TryAddSigned(T left, T right, out T result) + where T : IBinaryInteger, ISignedNumber { - sbyte result = (sbyte)(op1 + op2); - - bool ovf = false; - - if ((op1 > 0) && (op2 > 0)) - { - ovf = (result < 0); - } - else if ((op1 < 0) && (op2 < 0)) - { - ovf = (result > 0); - } - - return (result, ovf); - } - - private static (sbyte val, bool ovf) AddOvf(sbyte op1, byte op2) - { - sbyte result = (sbyte)(op1 + (sbyte)op2); - - bool ovf = (result < op1); - - return (result, ovf); + result = unchecked(left + right); + return ((result ^ left) & ~(left ^ right)) < T.Zero; } - private static (byte val, bool ovf) AddOvf(byte op1, sbyte op2) + private static bool TryAddUnsigned(T left, T right, out T result) + where T : IBinaryInteger, IUnsignedNumber { - byte result = (byte)(op1 + (byte)op2); - - bool ovf; - - if (op2 < 0) - { - ovf = (result > op1); - } - else - { - ovf = (result < op1); - } - - return (result, ovf); + result = left + right; + return result < left; } - private static (byte val, bool ovf) AddOvf(byte op1, byte op2) + private static bool TryAddSignedUnsigned( + TSigned left, TUnsigned right, out TSigned result) + where TSigned : IBinaryInteger, ISignedNumber + where TUnsigned : IBinaryInteger, IUnsignedNumber { - byte result = (byte)(op1 + op2); - - bool ovf = (result < op1); - - return (result, ovf); + result = unchecked(left + TSigned.CreateChecked(right)); + return result < left; } - private static (sbyte val, bool ovf) SubtractOvf(sbyte op1, sbyte op2) + private static bool TryAddUnsignedSigned( + TUnsigned left, TSigned right, out TUnsigned result) + where TUnsigned : IBinaryInteger, IUnsignedNumber + where TSigned : IBinaryInteger, ISignedNumber { - sbyte result = (sbyte)(op1 - op2); - - bool ovf; - - if (op2 < 0) + if (right < TSigned.Zero) { - ovf = (result < op1); + var mag = TUnsigned.CreateChecked(-right); + result = unchecked(left - mag); + return left < mag; } else { - ovf = (result > op1); + var add = TUnsigned.CreateChecked(right); + result = left + add; + return result < left; } - - return (result, ovf); } - private static (byte val, bool ovf) SubtractOvf(byte op1, byte op2) + private static bool TrySubSigned(T left, T right, out T result) + where T : IBinaryInteger, ISignedNumber { - byte result = (byte)(op1 - op2); - - bool ovf = (op1 < op2); + result = unchecked(left - right); + return ((left ^ right) & (left ^ result)) < T.Zero; + } - return (result, ovf); + private static bool TrySubUnsigned(T left, T right, out T result) + where T : IBinaryInteger, IUnsignedNumber + { + result = unchecked(left - right); + return left < right; } public static sbyte AbsSaturate(sbyte op1) => op1 < 0 ? NegateSaturate(op1) : op1; public static sbyte AddSaturate(sbyte op1, sbyte op2) { - int result = op1 + op2; - if (result > sbyte.MaxValue) + if (TryAddSigned(op1, op2, out sbyte result)) { - return sbyte.MaxValue; - } - else if (result < sbyte.MinValue) - { - return sbyte.MinValue; - } - else - { - return (sbyte)result; + result = (result < 0) ? sbyte.MaxValue : sbyte.MinValue; } + return result; } public static sbyte AddSaturate(sbyte op1, byte op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? sbyte.MaxValue : result; + if (TryAddSignedUnsigned(op1, op2, out sbyte result)) + { + result = (result < 0) ? sbyte.MaxValue : sbyte.MinValue; + } + return result; } public static byte AddSaturate(byte op1, sbyte op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? (result < op1 ? byte.MaxValue : byte.MinValue) : result; + if (TryAddUnsignedSigned(op1, op2, out byte result)) + { + result = (op2 < 0) ? (byte)0 : byte.MaxValue; + } + return result; } public static byte AddSaturate(byte op1, byte op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? byte.MaxValue : result; + if (TryAddUnsigned(op1, op2, out byte result)) + { + result = byte.MaxValue; + } + return result; } public static sbyte[] AddSaturateRotateComplex(sbyte[] op1, sbyte[] op2, byte rot) @@ -3273,14 +3250,20 @@ public static float AddSequentialAcross(float[] op1, float[] op2, float[] mask = public static sbyte SubtractSaturate(sbyte op1, sbyte op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? (result > 0 ? sbyte.MinValue : sbyte.MaxValue) : result; + if (TrySubSigned(op1, op2, out sbyte result)) + { + result = (result < 0) ? sbyte.MaxValue : sbyte.MinValue; + } + return result; } public static byte SubtractSaturate(byte op1, byte op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? byte.MinValue : result; + if (TrySubUnsigned(op1, op2, out byte result)) + { + result = byte.MinValue; + } + return result; } public static short ShiftArithmetic(short op1, short op2) => SignedShift(op1, op2); @@ -3313,7 +3296,7 @@ private static short SignedShift(short op1, short op2, bool rounding = false, bo bool addOvf; - (result, addOvf) = AddOvf(op1, rndCns); + addOvf = TryAddSigned(op1, rndCns, out result); if (addOvf) { @@ -3405,7 +3388,7 @@ private static ushort UnsignedShift(ushort op1, short op2, bool rounding = false } } - (ushort result, bool addOvf) = AddOvf(op1, rndCns); + bool addOvf = TryAddUnsigned(op1, rndCns, out ushort result); bool shiftOvf; @@ -3430,111 +3413,42 @@ private static ushort UnsignedShift(ushort op1, short op2, bool rounding = false private static short UnsignedShift(short op1, short op2, bool rounding = false, bool saturating = false) => (short)UnsignedShift((ushort)op1, op2, rounding, saturating); - private static (short val, bool ovf) AddOvf(short op1, short op2) - { - short result = (short)(op1 + op2); - - bool ovf = false; - - if ((op1 > 0) && (op2 > 0)) - { - ovf = (result < 0); - } - else if ((op1 < 0) && (op2 < 0)) - { - ovf = (result > 0); - } - - return (result, ovf); - } - - private static (short val, bool ovf) AddOvf(short op1, ushort op2) - { - short result = (short)(op1 + (short)op2); - - bool ovf = (result < op1); - - return (result, ovf); - } + public static short AbsSaturate(short op1) => op1 < 0 ? NegateSaturate(op1) : op1; - private static (ushort val, bool ovf) AddOvf(ushort op1, short op2) + public static short AddSaturate(short op1, short op2) { - ushort result = (ushort)(op1 + (ushort)op2); - - bool ovf; - - if (op2 < 0) - { - ovf = (result > op1); - } - else + if (TryAddSigned(op1, op2, out short result)) { - ovf = (result < op1); + result = (result < 0) ? short.MaxValue : short.MinValue; } - - return (result, ovf); - } - - private static (ushort val, bool ovf) AddOvf(ushort op1, ushort op2) - { - ushort result = (ushort)(op1 + op2); - - bool ovf = (result < op1); - - return (result, ovf); + return result; } - private static (short val, bool ovf) SubtractOvf(short op1, short op2) + public static short AddSaturate(short op1, ushort op2) { - short result = (short)(op1 - op2); - - bool ovf; - - if (op2 < 0) + if (TryAddSignedUnsigned(op1, op2, out short result)) { - ovf = (result < op1); + result = (result < 0) ? short.MaxValue : short.MinValue; } - else - { - ovf = (result > op1); - } - - return (result, ovf); - } - - private static (ushort val, bool ovf) SubtractOvf(ushort op1, ushort op2) - { - ushort result = (ushort)(op1 - op2); - - bool ovf = (op1 < op2); - - return (result, ovf); - } - - public static short AbsSaturate(short op1) => op1 < 0 ? NegateSaturate(op1) : op1; - - public static short AddSaturate(short op1, short op2) - { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? (result > 0 ? short.MinValue : short.MaxValue) : result; - } - - public static short AddSaturate(short op1, ushort op2) - { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? short.MaxValue : result; + return result; } public static ushort AddSaturate(ushort op1, short op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? (result < op1 ? ushort.MaxValue : ushort.MinValue) : result; + if (TryAddUnsignedSigned(op1, op2, out ushort result)) + { + result = (op2 < 0) ? (ushort)0 : ushort.MaxValue; + } + return result; } public static ushort AddSaturate(ushort op1, ushort op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? ushort.MaxValue : result; + if (TryAddUnsigned(op1, op2, out ushort result)) + { + result = ushort.MaxValue; + } + return result; } public static short[] AddSaturateRotateComplex(short[] op1, short[] op2, byte rot) @@ -3563,14 +3477,20 @@ public static short[] AddSaturateRotateComplex(short[] op1, short[] op2, byte ro public static short SubtractSaturate(short op1, short op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? (result > 0 ? short.MinValue : short.MaxValue) : result; + if (TrySubSigned(op1, op2, out short result)) + { + result = (result < 0) ? short.MaxValue : short.MinValue; + } + return result; } public static ushort SubtractSaturate(ushort op1, ushort op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? ushort.MinValue : result; + if (TrySubUnsigned(op1, op2, out ushort result)) + { + result = ushort.MinValue; + } + return result; } public static int ShiftArithmetic(int op1, int op2) => SignedShift(op1, op2); @@ -3603,7 +3523,7 @@ private static int SignedShift(int op1, int op2, bool rounding = false, bool sat bool addOvf; - (result, addOvf) = AddOvf(op1, rndCns); + addOvf = TryAddSigned(op1, rndCns, out result); if (addOvf) { @@ -3695,7 +3615,8 @@ private static uint UnsignedShift(uint op1, int op2, bool rounding = false, bool } } - (uint result, bool addOvf) = AddOvf(op1, rndCns); + uint result; + bool addOvf = TryAddUnsigned(op1, rndCns, out result); bool shiftOvf; @@ -3720,111 +3641,42 @@ private static uint UnsignedShift(uint op1, int op2, bool rounding = false, bool private static int UnsignedShift(int op1, int op2, bool rounding = false, bool saturating = false) => (int)UnsignedShift((uint)op1, op2, rounding, saturating); - private static (int val, bool ovf) AddOvf(int op1, int op2) - { - int result = (int)(op1 + op2); - - bool ovf = false; - - if ((op1 > 0) && (op2 > 0)) - { - ovf = (result < 0); - } - else if ((op1 < 0) && (op2 < 0)) - { - ovf = (result > 0); - } - - return (result, ovf); - } - - private static (int val, bool ovf) AddOvf(int op1, uint op2) - { - int result = (int)(op1 + (int)op2); - - bool ovf = (result < op1); - - return (result, ovf); - } + public static int AbsSaturate(int op1) => op1 < 0 ? NegateSaturate(op1) : op1; - private static (uint val, bool ovf) AddOvf(uint op1, int op2) + public static int AddSaturate(int op1, int op2) { - uint result = (uint)(op1 + (uint)op2); - - bool ovf; - - if (op2 < 0) - { - ovf = (result > op1); - } - else + if (TryAddSigned(op1, op2, out int result)) { - ovf = (result < op1); + result = (result < 0) ? int.MaxValue : int.MinValue; } - - return (result, ovf); - } - - private static (uint val, bool ovf) AddOvf(uint op1, uint op2) - { - uint result = (uint)(op1 + op2); - - bool ovf = (result < op1); - - return (result, ovf); + return result; } - private static (int val, bool ovf) SubtractOvf(int op1, int op2) + public static int AddSaturate(int op1, uint op2) { - int result = (int)(op1 - op2); - - bool ovf; - - if (op2 < 0) + if (TryAddSignedUnsigned(op1, op2, out int result)) { - ovf = (result < op1); + result = (result < 0) ? int.MaxValue : int.MinValue; } - else - { - ovf = (result > op1); - } - - return (result, ovf); - } - - private static (uint val, bool ovf) SubtractOvf(uint op1, uint op2) - { - uint result = (uint)(op1 - op2); - - bool ovf = (op1 < op2); - - return (result, ovf); - } - - public static int AbsSaturate(int op1) => op1 < 0 ? NegateSaturate(op1) : op1; - - public static int AddSaturate(int op1, int op2) - { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? (result > 0 ? int.MinValue : int.MaxValue) : result; - } - - public static int AddSaturate(int op1, uint op2) - { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? int.MaxValue : result; + return result; } public static uint AddSaturate(uint op1, int op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? (result < op1 ? uint.MaxValue : uint.MinValue) : result; + if (TryAddUnsignedSigned(op1, op2, out uint result)) + { + result = (op2 < 0) ? (uint)0 : uint.MaxValue; + } + return result; } public static uint AddSaturate(uint op1, uint op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? uint.MaxValue : result; + if (TryAddUnsigned(op1, op2, out uint result)) + { + result = uint.MaxValue; + } + return result; } public static int[] AddSaturateRotateComplex(int[] op1, int[] op2, byte rot) @@ -3853,14 +3705,20 @@ public static int[] AddSaturateRotateComplex(int[] op1, int[] op2, byte rot) public static int SubtractSaturate(int op1, int op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? (result > 0 ? int.MinValue : int.MaxValue) : result; + if (TrySubSigned(op1, op2, out int result)) + { + result = (result < 0) ? int.MaxValue : int.MinValue; + } + return result; } public static uint SubtractSaturate(uint op1, uint op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? uint.MinValue : result; + if (TrySubUnsigned(op1, op2, out uint result)) + { + result = uint.MinValue; + } + return result; } public static long ShiftArithmetic(long op1, long op2) => SignedShift(op1, op2); @@ -3893,7 +3751,7 @@ private static long SignedShift(long op1, long op2, bool rounding = false, bool bool addOvf; - (result, addOvf) = AddOvf(op1, rndCns); + addOvf = TryAddSigned(op1, rndCns, out result); if (addOvf) { @@ -3985,7 +3843,8 @@ private static ulong UnsignedShift(ulong op1, long op2, bool rounding = false, b } } - (ulong result, bool addOvf) = AddOvf(op1, rndCns); + ulong result; + bool addOvf = TryAddUnsigned(op1, rndCns, out result); bool shiftOvf; @@ -4010,111 +3869,43 @@ private static ulong UnsignedShift(ulong op1, long op2, bool rounding = false, b private static long UnsignedShift(long op1, long op2, bool rounding = false, bool saturating = false) => (long)UnsignedShift((ulong)op1, op2, rounding, saturating); - private static (long val, bool ovf) AddOvf(long op1, long op2) - { - long result = (long)(op1 + op2); - - bool ovf = false; + public static long AbsSaturate(long op1) => op1 < 0 ? NegateSaturate(op1) : op1; - if ((op1 > 0) && (op2 > 0)) - { - ovf = (result < 0); - } - else if ((op1 < 0) && (op2 < 0)) + public static long AddSaturate(long op1, long op2) + { + if (TryAddSigned(op1, op2, out long result)) { - ovf = (result > 0); + result = (result < 0) ? long.MaxValue : long.MinValue; } - - return (result, ovf); - } - - private static (long val, bool ovf) AddOvf(long op1, ulong op2) - { - long result = (long)(op1 + (long)op2); - - bool ovf = (result < op1); - - return (result, ovf); + return result; } - private static (ulong val, bool ovf) AddOvf(ulong op1, long op2) + public static long AddSaturate(long op1, ulong op2) { - ulong result = (ulong)(op1 + (ulong)op2); - - bool ovf; - - if (op2 < 0) + if (TryAddSignedUnsigned(op1, op2, out long result)) { - ovf = (result > op1); + result = (result < 0) ? long.MaxValue : long.MinValue; } - else - { - ovf = (result < op1); - } - - return (result, ovf); - } - - private static (ulong val, bool ovf) AddOvf(ulong op1, ulong op2) - { - ulong result = (ulong)(op1 + op2); - - bool ovf = (result < op1); - - return (result, ovf); + return result; } - private static (long val, bool ovf) SubtractOvf(long op1, long op2) + public static ulong AddSaturate(ulong op1, long op2) { - long result = (long)(op1 - op2); - - bool ovf; - - if (op2 < 0) + if (TryAddUnsignedSigned(op1, op2, out ulong result)) { - ovf = (result < op1); + result = (op2 < 0) ? (ulong)0 : ulong.MaxValue; } - else - { - ovf = (result > op1); - } - - return (result, ovf); - } - - private static (ulong val, bool ovf) SubtractOvf(ulong op1, ulong op2) - { - ulong result = (ulong)(op1 - op2); - - bool ovf = (op1 < op2); - - return (result, ovf); - } - - public static long AbsSaturate(long op1) => op1 < 0 ? NegateSaturate(op1) : op1; - - public static long AddSaturate(long op1, long op2) - { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? (result > 0 ? long.MinValue : long.MaxValue) : result; - } - - public static long AddSaturate(long op1, ulong op2) - { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? long.MaxValue : result; + return result; } - public static ulong AddSaturate(ulong op1, long op2) - { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? (result < op1 ? ulong.MaxValue : ulong.MinValue) : result; - } public static ulong AddSaturate(ulong op1, ulong op2) { - var (result, ovf) = AddOvf(op1, op2); - return ovf ? ulong.MaxValue : result; + if (TryAddUnsigned(op1, op2, out ulong result)) + { + result = ulong.MaxValue; + } + return result; } public static long[] AddSaturateRotateComplex(long[] op1, long[] op2, byte rot) @@ -4143,17 +3934,22 @@ public static long[] AddSaturateRotateComplex(long[] op1, long[] op2, byte rot) public static long SubtractSaturate(long op1, long op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? (result > 0 ? long.MinValue : long.MaxValue) : result; + if (TrySubSigned(op1, op2, out long result)) + { + result = (result < 0) ? long.MaxValue : long.MinValue; + } + return result; } public static ulong SubtractSaturate(ulong op1, ulong op2) { - var (result, ovf) = SubtractOvf(op1, op2); - return ovf ? ulong.MinValue : result; + if (TrySubUnsigned(op1, op2, out ulong result)) + { + result = ulong.MinValue; + } + return result; } - private static (sbyte val, bool ovf) ShiftOvf(sbyte value, int shift) { sbyte result = value;