Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RISC-V] Fix Int32 to Unsigned overflow check #107024

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b112859
[RISC-V] Allowed CHECK_POSITIVE to have temporary register
Bajtazar Aug 26, 2024
f3fb8b3
[RISC-V] Fixed CHECK_POSITIVE in genIntCastOverflowCheck
Bajtazar Aug 26, 2024
9054a4e
[RISC-V] Improved J pseudoinstruction printing
Bajtazar Aug 26, 2024
1f7c669
[RISC-V] Added ret pseudoinstruction to disasm
Bajtazar Aug 26, 2024
4dcc555
[RISC-V] Fixed register type in disasm
Bajtazar Aug 26, 2024
144629f
[RISC-V] Fixed ins_Load
Bajtazar Aug 27, 2024
0a595fb
[RISC-V] Formatted code
Bajtazar Aug 27, 2024
87105a9
Merge branch 'main' into riscv-positive-int-overflow-fix
Bajtazar Aug 27, 2024
c68c1cd
[RISC-V] Fixed format bug
Bajtazar Aug 27, 2024
9b268e9
Merge branch 'riscv-positive-int-overflow-fix' of github.com:Bajtazar…
Bajtazar Aug 27, 2024
bd678ee
Revert "[RISC-V] Fixed ins_Load"
Bajtazar Aug 27, 2024
4bef7fb
[RISC-V] Fixed comment in codegenlinear
Bajtazar Aug 27, 2024
eea0be5
[RISC-V] Fixed sextw attribute type
Bajtazar Aug 27, 2024
cdb7924
[RISC-V] Simplified casts logic
Bajtazar Aug 27, 2024
1b4907e
[RISC-V] Improved CHECK_SMALL_INT_RANGE casts
Bajtazar Aug 27, 2024
d063b64
[RISC-V] Optimized check int range
Bajtazar Aug 27, 2024
4dffd5f
[RISC-V] Fixes in codegenriscv64
Bajtazar Aug 27, 2024
74868f2
[RISC-V] Removed unused comment
Bajtazar Aug 27, 2024
bc09d23
[RISC-V] Fixed long/ulong casts
Bajtazar Aug 27, 2024
44e7411
[RISC-V] Added some comments
Bajtazar Aug 27, 2024
75d7405
[RISC-V] Fixes in CHECK_SMALL_INT_RANGE
Bajtazar Aug 28, 2024
eba998a
[RISC-V] More bugfixes in int casts
Bajtazar Aug 28, 2024
5fdc67f
[RISC-V] Generalized CHECK_SMALL_INT_RANGE a little bit
Bajtazar Aug 29, 2024
209a8b1
Merge branch 'main' into riscv-positive-int-overflow-fix
Bajtazar Sep 3, 2024
5db2482
[RISC-V] Fixed typo
Bajtazar Sep 3, 2024
97c951c
Merge branch 'main' into riscv-positive-int-overflow-fix
Bajtazar Sep 3, 2024
daa73aa
Merge branch 'main' into riscv-positive-int-overflow-fix
Bajtazar Sep 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/coreclr/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2526,7 +2526,7 @@ CodeGen::GenIntCastDesc::GenIntCastDesc(GenTreeCast* cast)
break;

#ifdef TARGET_64BIT
case ZERO_EXTEND_INT: // ubyte/ushort/int -> long.
case ZERO_EXTEND_INT: // ubyte/ushort/uint -> long.
assert(varTypeIsUnsigned(srcLoadType) || (srcLoadType == TYP_INT));
m_extendKind = varTypeIsSmall(srcLoadType) ? LOAD_ZERO_EXTEND_SMALL_INT : LOAD_ZERO_EXTEND_INT;
m_extendSrcSize = genTypeSize(srcLoadType);
Expand Down
109 changes: 50 additions & 59 deletions src/coreclr/jit/codegenriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6227,90 +6227,81 @@ void CodeGen::genJmpPlaceVarArgs()
//
void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& desc, regNumber reg)
{
const regNumber tempReg = internalRegisters.GetSingle(cast);

switch (desc.CheckKind())
{
// int -> uint/ulong
// uint -> int
// long -> ulong
// ulong -> long
case GenIntCastDesc::CHECK_POSITIVE:
{
if (desc.CheckSrcSize() == 4) // is int or uint
{
// If uint is bigger than INT32_MAX then it will be treated as a signed
// number so overflow will also be triggered
GetEmitter()->emitIns_R_R(INS_sext_w, EA_4BYTE, tempReg, reg);
reg = tempReg;
}
// Check if integral is smaller than zero
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_blt, reg, nullptr, REG_R0);
Copy link
Contributor Author

@Bajtazar Bajtazar Aug 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am correct this piece of code is invoked during uint -> int conversion. That would mean that if the uint > 0x7f'ff'ff'ff the old comparation wouldn't work since it wouldn't be classified as an overflow

}
break;

// ulong/long -> uint
case GenIntCastDesc::CHECK_UINT_RANGE:
{
regNumber tempReg = internalRegisters.GetSingle(cast);
// We need to check if the value is not greater than 0xFFFFFFFF
// if the upper 32 bits are zero.
ssize_t imm = -1;
GetEmitter()->emitIns_R_R_I(INS_addi, EA_8BYTE, tempReg, REG_R0, imm);

GetEmitter()->emitIns_R_R_I(INS_slli, EA_8BYTE, tempReg, tempReg, 32);
GetEmitter()->emitIns_R_R_R(INS_and, EA_8BYTE, tempReg, reg, tempReg);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg);
// Check if upper 32-bits are zeros
GetEmitter()->emitIns_R_R_I(INS_srli, EA_8BYTE, tempReg, reg, 32);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, REG_R0);
}
break;

// ulong -> int
case GenIntCastDesc::CHECK_POSITIVE_INT_RANGE:
{
regNumber tempReg = internalRegisters.GetSingle(cast);
// We need to check if the value is not greater than 0x7FFFFFFF
// if the upper 33 bits are zero.
// instGen_Set_Reg_To_Imm(EA_8BYTE, tempReg, 0xFFFFFFFF80000000LL);
ssize_t imm = -1;
GetEmitter()->emitIns_R_R_I(INS_addi, EA_8BYTE, tempReg, REG_R0, imm);

GetEmitter()->emitIns_R_R_I(INS_slli, EA_8BYTE, tempReg, tempReg, 31);

GetEmitter()->emitIns_R_R_R(INS_and, EA_8BYTE, tempReg, reg, tempReg);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg);
// Check if upper 33-bits are zeros (biggest allowed value is 0x7FFFFFFF)
GetEmitter()->emitIns_R_R_I(INS_srli, EA_8BYTE, tempReg, reg, 31);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, REG_R0);
}
break;

// long -> int
case GenIntCastDesc::CHECK_INT_RANGE:
{
const regNumber tempReg = internalRegisters.GetSingle(cast);
assert(tempReg != reg);
GetEmitter()->emitLoadImmediate(EA_8BYTE, tempReg, INT32_MAX);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_blt, tempReg, nullptr, reg);

GetEmitter()->emitLoadImmediate(EA_8BYTE, tempReg, INT32_MIN);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_blt, reg, nullptr, tempReg);
// Extend sign of lower half of long so that it overrides its upper half
// If a new value differs from the original then the upper half was not
// a pure sign extension so there is an overflow
GetEmitter()->emitIns_R_R(INS_sext_w, EA_4BYTE, tempReg, reg);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, reg);
}
break;

default:
// * -> short/ushort/byte/ubyte
default: // CHECK_SMALL_INT_RANGE
{
assert(desc.CheckKind() == GenIntCastDesc::CHECK_SMALL_INT_RANGE);
const int castMaxValue = desc.CheckSmallIntMax();
const int castMinValue = desc.CheckSmallIntMin();
const regNumber tempReg = internalRegisters.GetSingle(cast);
instruction ins;

if (castMaxValue > 2047)
{
assert((castMaxValue == 32767) || (castMaxValue == 65535));
GetEmitter()->emitLoadImmediate(EA_ATTR(desc.CheckSrcSize()), tempReg, castMaxValue + 1);
ins = castMinValue == 0 ? INS_bgeu : INS_bge;
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, ins, reg, nullptr, tempReg);
}
else
{
GetEmitter()->emitIns_R_R_I(INS_addiw, EA_ATTR(desc.CheckSrcSize()), tempReg, REG_R0, castMaxValue);
ins = castMinValue == 0 ? INS_bltu : INS_blt;
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, ins, tempReg, nullptr, reg);
}

if (castMinValue != 0)
{
if (emitter::isValidSimm12(castMinValue))
{
GetEmitter()->emitIns_R_R_I(INS_slti, EA_ATTR(desc.CheckSrcSize()), tempReg, reg, castMinValue);
}
else
{
GetEmitter()->emitLoadImmediate(EA_8BYTE, tempReg, castMinValue);
GetEmitter()->emitIns_R_R_R(INS_slt, EA_ATTR(desc.CheckSrcSize()), tempReg, reg, tempReg);
}
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg);
const unsigned castSize = genTypeSize(cast->gtCastType);
const bool isSrcOrDstUnsigned = desc.CheckSmallIntMin() == 0;

if (isSrcOrDstUnsigned)
{
// Check if bits leading the actual small int are all zeros
// If destination type is signed then also check if MSB of it is zero
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);
genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_bne, tempReg, nullptr, REG_R0);
}
else // Signed to signed cast
{
// Extend sign of a small int on all of the bits above it and check whether the original type was same
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);
}
}
break;
Expand Down
26 changes: 21 additions & 5 deletions src/coreclr/jit/emitriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3914,14 +3914,21 @@ void emitter::emitDispInsName(
}
case 0x67:
{
const char* rs1 = RegNames[(code >> 15) & 0x1f];
const char* rd = RegNames[(code >> 7) & 0x1f];
int offset = ((code >> 20) & 0xfff);
const unsigned rs1 = (code >> 15) & 0x1f;
const unsigned rd = (code >> 7) & 0x1f;
int offset = ((code >> 20) & 0xfff);
if (offset & 0x800)
{
offset |= 0xfffff000;
}
printf("jalr %s, %d(%s)", rd, offset, rs1);

if ((rs1 == REG_RA) && (rd == REG_ZERO))
{
printf("ret");
return;
}

printf("jalr %s, %d(%s)", RegNames[rd], offset, RegNames[rs1]);
CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
// Target for ret call is unclear, e.g.:
// jalr zero, 0(ra)
Expand All @@ -3946,7 +3953,16 @@ void emitter::emitDispInsName(
}
if (rd == REG_ZERO)
{
printf("j %d", offset);
printf("j ");

if (id->idIsBound())
{
emitPrintLabel(id->idAddr()->iiaIGlabel);
}
else
{
printf("pc%+d instructions", offset >> 2);
Bajtazar marked this conversation as resolved.
Show resolved Hide resolved
}
}
else
{
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/lsrariscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode)
int LinearScan::BuildCast(GenTreeCast* cast)
{
enum CodeGen::GenIntCastDesc::CheckKind kind = CodeGen::GenIntCastDesc(cast).CheckKind();
if ((kind != CodeGen::GenIntCastDesc::CHECK_NONE) && (kind != CodeGen::GenIntCastDesc::CHECK_POSITIVE))
if ((kind != CodeGen::GenIntCastDesc::CHECK_NONE))
{
buildInternalIntRegisterDefForNode(cast);
}
Expand Down
Loading