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

JitArm64: Fix crandc/creqv/crorc setting eq bit #13266

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

JosJuice
Copy link
Member

@JosJuice JosJuice commented Jan 6, 2025

When I wrote 71e9766, there was an interaction I didn't take into account: When setting eq, SetCRFieldBit assumes that all bits in the passed-in host register except the least significant bit are 0. But if we use BIC/EON/ORN, all bits except the least significant bit get set to 1. This can cause eq to end up unset when it should be set.

This pull request fixes the issue.

@JosJuice JosJuice force-pushed the jitarm64-cr-bits-1-to-31 branch from 913ecce to 82695ea Compare January 6, 2025 10:49
Copy link
Contributor

@Dentomologist Dentomologist left a comment

Choose a reason for hiding this comment

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

crXXX assigns to bits_1_to_31_are_set but doesn't use it anywhere. I presume it's supposed to be an argument for the SetCRFieldBit call at the end of the function?

@JosJuice
Copy link
Member Author

Yes! That's an embarrassing mistake :(

When I wrote 71e9766, there was an interaction I didn't take into
account: When setting eq, SetCRFieldBit assumes that all bits in the
passed-in host register except the least significant bit are 0. But if
we use BIC/EON/ORN, all bits except the least significant bit get set to
1. This can cause eq to end up unset when it should be set.

This commit fixes the issue.

Note that in practice, we never have both bits_1_to_31_are_set and
negate at once, so while it looks like this commit adds an extra AND
instruction in some cases, those cases don't happen in practice, meaning
this fix shouldn't affect performance.
For the eq and gt bits specifically, setting negate_result is one
instruction shorter than not setting it.
@JosJuice JosJuice force-pushed the jitarm64-cr-bits-1-to-31 branch from 82695ea to 6678af3 Compare January 11, 2025 12:43
Comment on lines 71 to 77
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0000, GPRSize::B64));
ORR(CR, CR, in);
if (!negate)
EOR(CR, CR, LogicalImm(1ULL << 0, GPRSize::B64));
EOR(CR, CR, LogicalImm(bits_1_to_31_are_set ? 0xFFFF'FFFFULL : 1ULL, GPRSize::B64));
else if (bits_1_to_31_are_set)
AND(CR, CR, LogicalImm(0xFFFF'FFFF'0000'0001ULL, GPRSize::B64));
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suppose we replaced this whole CR_EQ_BIT case with a BFI of the lower 32 bits (which would handle the combination where negate is true and bits_1_to_31_are_set is false), then EOR with 0x1, 0xFFFF'FFFE, or 0xFFFF'FFFF for the other three combinations respectively. That would make each combination 1 or 2 instructions; are there any downsides I'm missing?

Comment on lines 659 to 662
case 129: // crandc: A && ~B
BIC(XA, XA, XB);
BIC(WA, WA, WB);
bits_1_to_31_are_set = true;
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

A is either 0 or 1, right? If so A && ~B should result in 0 or 1 too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants