diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index aa4abea743baca..82972766243478 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -1308,7 +1308,9 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode) else if (data->IsIntegralConst()) { ssize_t cnsVal = data->AsIntConCommon()->IconValue(); - dataReg = (targetReg == REG_NA) ? rsGetRsvdReg() : targetReg; // Use tempReg if spilled + // If spilled, use RA as the temp: the reserved register may be needed below + // to form the address of a stack local whose offset does not fit in simm12. + dataReg = (targetReg == REG_NA) ? REG_RA : targetReg; if (data->IsIconHandle() && data->AsIntCon()->FitsInAddrBase(m_compiler) && data->AsIntCon()->AddrNeedsReloc(m_compiler)) @@ -5695,7 +5697,11 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d const bool isDstSigned = !varTypeIsUnsigned(cast->gtCastType); const unsigned excludeMsb = isDstSigned ? 1 : 0; const unsigned typeSize = 8 * castSize - excludeMsb; - GetEmitter()->emitIns_R_R_I(INS_srli, EA_8BYTE, tempReg, reg, typeSize); + // The upper 32 bits of an (u)int source are not guaranteed to be sign-extended, + // so only shift within the lower 32 bits + const bool isSrcInt = desc.CheckSrcSize() == 4; + GetEmitter()->emitIns_R_R_I(isSrcInt ? INS_srliw : INS_srli, isSrcInt ? EA_4BYTE : EA_8BYTE, tempReg, + reg, typeSize); genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, REG_R0); } else // Signed to signed cast @@ -5704,7 +5710,17 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d const auto extensionSize = (8 - castSize) * 8; GetEmitter()->emitIns_R_R_I(INS_slli, EA_8BYTE, tempReg, reg, extensionSize); GetEmitter()->emitIns_R_R_I(INS_srai, EA_8BYTE, tempReg, tempReg, extensionSize); - genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, reg); + if (desc.CheckSrcSize() == 4) // int + { + // The upper 32 bits of an int source are not guaranteed to be sign-extended, + // so compare only the lower 32 bits + GetEmitter()->emitIns_R_R_R(INS_subw, EA_4BYTE, tempReg, tempReg, reg); + genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, REG_R0); + } + else + { + genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, reg); + } } } break; diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 9dcd3a29d7aaab..27a36e5cfd6332 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -369,6 +369,8 @@ void emitter::emitIns_S_R_R(instruction ins, emitAttr attr, regNumber reg1, regN // If immediate does not fit to store immediate 12 bits, construct necessary value in rsRsvdReg() // and keep tmpReg hint value unchanged. assert(isValidSimm20((imm + 0x800) >> 12)); + // The value being stored must not live in rsRsvdReg(), it would be overwritten by the address + assert(reg1 != codeGen->rsGetRsvdReg()); emitIns_R_I(INS_lui, EA_PTRSIZE, codeGen->rsGetRsvdReg(), (imm + 0x800) >> 12); emitIns_R_R_R(INS_add, EA_PTRSIZE, codeGen->rsGetRsvdReg(), codeGen->rsGetRsvdReg(), reg2); diff --git a/src/libraries/System.Runtime.Numerics/tests/ComplexTests.SpecialValues.cs b/src/libraries/System.Runtime.Numerics/tests/ComplexTests.SpecialValues.cs index 8f0365e155ba47..7344bccd2f9bdf 100644 --- a/src/libraries/System.Runtime.Numerics/tests/ComplexTests.SpecialValues.cs +++ b/src/libraries/System.Runtime.Numerics/tests/ComplexTests.SpecialValues.cs @@ -365,9 +365,11 @@ public static void Cos(double real, double imaginary, double expectedReal, doubl [MemberData(nameof(Tan_SpecialValues))] public static void Tan(double real, double imaginary, double expectedReal, double expectedImaginary) { - Verify(Complex.Tan, "Tan", real, imaginary, expectedReal, expectedImaginary); - Verify(Complex.Tan, "Tan", real, imaginary, expectedReal, expectedImaginary); - Verify(Complex.Tan, "Tan", real, imaginary, expectedReal, expectedImaginary); + // The sign of a zero result is taken from a NaN input, whose sign is not preserved on every platform. + bool exactZeroSign = PlatformDetection.IsNaNPayloadPreservationExpected || (!double.IsNaN(real) && !double.IsNaN(imaginary)); + Verify(Complex.Tan, "Tan", real, imaginary, expectedReal, expectedImaginary, exactZeroSign); + Verify(Complex.Tan, "Tan", real, imaginary, expectedReal, expectedImaginary, exactZeroSign); + Verify(Complex.Tan, "Tan", real, imaginary, expectedReal, expectedImaginary, exactZeroSign); } [Theory] @@ -392,9 +394,11 @@ public static void Cosh(double real, double imaginary, double expectedReal, doub [MemberData(nameof(Tanh_SpecialValues))] public static void Tanh(double real, double imaginary, double expectedReal, double expectedImaginary) { - Verify(Complex.Tanh, "Tanh", real, imaginary, expectedReal, expectedImaginary); - Verify(Complex.Tanh, "Tanh", real, imaginary, expectedReal, expectedImaginary); - Verify(Complex.Tanh, "Tanh", real, imaginary, expectedReal, expectedImaginary); + // The sign of a zero result is taken from a NaN input, whose sign is not preserved on every platform. + bool exactZeroSign = PlatformDetection.IsNaNPayloadPreservationExpected || (!double.IsNaN(real) && !double.IsNaN(imaginary)); + Verify(Complex.Tanh, "Tanh", real, imaginary, expectedReal, expectedImaginary, exactZeroSign); + Verify(Complex.Tanh, "Tanh", real, imaginary, expectedReal, expectedImaginary, exactZeroSign); + Verify(Complex.Tanh, "Tanh", real, imaginary, expectedReal, expectedImaginary, exactZeroSign); } [Fact]