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 invalid operand register in the emitted addition/subtraction code #102074

Open
wants to merge 30 commits into
base: main
Choose a base branch
from

Conversation

Bajtazar
Copy link
Contributor

@Bajtazar Bajtazar commented May 10, 2024

Fixes invalid operand register in the emitted addition/subtraction code when both of the operand registers are same. Slightly improves quality of the generated code. Also introduces sext.w preudoinstruction to replace double-shift sign extension snippets

Examples of old and new code:

; Old long overflow check
     mv      a0, s1
     add     s1, s1, s1
     srli    ra, a0, 63
     srli    a1, s1, 63 ; s1 should be a0 which was the cause of the bug
     xor     ra, ra, a1
     bnez    ra, label_1
     bnez    a1, label_2
     bge     s1, a0, label_1
label_3:
     j       overflow
label_2:
     blt     a0, s1, label_3 
label_1:
     ; valid code

; New long overflow check
     mv      a0, s1
     add     s1, s1, s1
     slt     a1, s1, a0
     slti    a0, a0, 0
     bne     a1, a0, overflow
     ; valid code

; Old int overflow check
     mv      a0, s1
     addw    s1, s1, s1
     srli    ra, a0, 31
     srli    a1, s1, 31 ; same problem with s1 instead of a0
     xor     ra, ra, a1
     andi    ra, ra, 1
     andi    a1, a1, 1
     bnez    ra, label_1
     bnez    a1, label_2
     bge     s1, a0, label_1
label_3:
     j       overflow
label_2:
     blt     a0, s1, label_3 
label_1:
    ; valid code

; New int overflow check
     mv      a0, s1
     addw    s1, s1, s1
     add     a1, a0, a0
     bne     s1, a1, overflow
    ; valid code

Part of #84834, cc @dotnet/samsung

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 10, 2024
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label May 10, 2024
Copy link
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

@tomeksowi
Copy link
Contributor

; Old long overflow check
     mv      a0, s1
     add     s1, s1, s1
     srli    ra, a0, 63
     srli    a1, s1, 63 ; s1 should be a0 which was the cause of the bug
     xor     ra, ra, a1

If s1 would be a0 in this snippet, both ra and a1 would have the same value after right shifts, so the xor below would always return 0, no?

@Bajtazar
Copy link
Contributor Author

; Old long overflow check
     mv      a0, s1
     add     s1, s1, s1
     srli    ra, a0, 63
     srli    a1, s1, 63 ; s1 should be a0 which was the cause of the bug
     xor     ra, ra, a1

If s1 would be a0 in this snippet, both ra and a1 would have the same value after right shifts, so the xor below would always return 0, no?

Yes, this second shift was supposed to calculate whether the original second operand was negative but since the logic responsible for preserving the original's operands value wasn't prepared for the case where both of the operand registers were same and thus allowing the bug to happen. After fixing it it also implied that ra would always be equal to zero rendering it and its branch useless in this case, so I've decided to reshape the emitter a little bit

src/coreclr/jit/emitriscv64.cpp Outdated Show resolved Hide resolved
src/coreclr/jit/emitriscv64.cpp Outdated Show resolved Hide resolved
src/coreclr/jit/emitriscv64.cpp Outdated Show resolved Hide resolved
@clamp03 clamp03 added the arch-riscv Related to the RISC-V architecture label May 10, 2024
@@ -588,7 +588,7 @@ void emitter::emitIns_R_R(
{
code_t code = emitInsCode(ins);

if (INS_mov == ins)
if (INS_mov == ins || INS_sext_w == ins)
Copy link
Member

Choose a reason for hiding this comment

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

Have you discussed in your team to use pseudo code actively in JIT?
Actually, I want to remove all pseudo codes like mov in JITC because some pseudo codes (contains multiple normal instructions) cannot be used in JIT.

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO simple "renaming" pseudos like sext.w, bnez, mov, etc, are fine. We're already using them, they convey the intention a bit more clearly, and they make the assembly look closer to print-outs from native compilers.

I agree about multi-instruction pseudos, though.

Copy link
Member

@clamp03 clamp03 May 10, 2024

Choose a reason for hiding this comment

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

Okay. Actually, we used few pesudos in few code locations, however AFAIK it is not printed properly in dump. I just let those instruction because I hope removing later. If you want to use pseudos. Could you add such instructions like 'mov' and 'nop' in emitDispInsName too?
Thank you.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can add pseudos to the disassm but I would prefer to do it in other PR. Would you mind?

@clamp03
Copy link
Member

clamp03 commented May 10, 2024

Which tests can you fix by this PR?


codeGen->genDefineTempLabel(tmpLabel);
// if ((A < B) != (C < 0)) then overflow
Copy link
Member

@clamp03 clamp03 May 10, 2024

Choose a reason for hiding this comment

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

For subtraction, is it correct comment?
I think if B = A - C is right for sub, this comment should be update or if A = B - C is right for sub, then // if B > A then overflow in line 5037 should be update.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMO it is Ok, I've used the property of the overflows in RISCV64 that operations ignore overflow and wraps around 2^64. Due to this if A = B - C overflows then B = A + C does too. I've shuffled registers at the beginning according to the type of the operation so that at the end I just checks whether there is an addition overflow

Copy link
Member

Choose a reason for hiding this comment

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

I was confused. Thank you for your explanation.

@Bajtazar
Copy link
Contributor Author

Which tests can you fix by this PR?

It fixes JIT/jit64/rtchecks/overflow/overflow04_add/overflow04_add.sh and during testing it also seems to fix JIT/opt/virtualstubdispatch/bigvtbl/bigvtbl_cs_d/bigvtbl_cs_d.sh

@clamp03
Copy link
Member

clamp03 commented May 22, 2024

@jakobbotsch Could you review this PR? Thank you.

@clamp03 clamp03 requested a review from jakobbotsch May 22, 2024 00:35
@risc-vv
Copy link

risc-vv commented May 24, 2024

RISC-V testing failed on init-build

GIT: e464442

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
arch-riscv Related to the RISC-V architecture area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants