-
Notifications
You must be signed in to change notification settings - Fork 5k
JIT: Add morphing to LE_UN/GT_UN(expr, uint.MaxValue) (dotnet#76525) #113037
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch |
@dotnet-policy-service agree company="Microsoft" |
Seems like CI failed with
|
src/coreclr/jit/morph.cpp
Outdated
GenTreeOp* shiftNode = gtNewOperNode(GT_RSZ, TYP_LONG, op1, icon32); | ||
shiftNode->SetMorphed(this); | ||
|
||
cmp->gtOp1 = shiftNode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EQ/NE(RSZ(expr, 32), 0).
I don't see where that 0
is set here, what is cmp->gtOp2
at this point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this line sets op2 to 0. All other morphing done in fgOptimizeRelationalComparisonWithConst
also don't set 0 explicitly.
runtime/src/coreclr/jit/morph.cpp
Line 9400 in 63a3a5f
op2->SetIntegralValue(0); |
That's probably because this PR isn't handling the things pointed out here: #76525 (comment) |
Thank you for pointing it out. Will check the issue comment and fix. |
4fe1edc
to
907e97c
Compare
src/coreclr/jit/lower.cpp
Outdated
#ifdef TARGET_XARCH | ||
// Do not optimize, BMI2 shrx does not set zero flag | ||
if (op1->OperIs(GT_RSZ) && !op1->AsOp()->gtGetOp2()->OperIsConst()) | ||
{ | ||
return cmp; | ||
} | ||
#endif // TARGET_XARCH |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like CI failed with
ISSUE: <ASSERT> #263216 D:\a\_work\1\s\src\coreclr\jit\codegenxarch.cpp (4912) - Assertion failed 'operandReg != REG_RCX' in 'bug.Program:TestEntryPoint():int' during 'Generate code' (IL size 42; hash 0x8feb9733; FullOpts)
That's probably because this PR isn't handling the things pointed out here: #76525 (comment)
@jakobbotsch I've implemented the exclusion logic based on your comment. Can you check this? I've thought of checking op2 in LowerShift() and set the flag which tells OptimizeConstCompare() not to optimize, but I think that's redundant and went for directly checking op2 of GT_RSZ here.
src/coreclr/jit/lower.cpp
Outdated
@@ -4181,6 +4181,13 @@ GenTree* Lowering::OptimizeConstCompare(GenTree* cmp) | |||
if (cmp->OperIs(GT_EQ, GT_NE) && op2->IsIntegralConst(0) && op1->SupportsSettingZeroFlag() && | |||
BlockRange().TryGetUse(cmp, &use)) | |||
{ | |||
#ifdef TARGET_XARCH | |||
// Do not optimize, BMI2 shrx does not set zero flag | |||
if (op1->OperIs(GT_RSZ) && !op1->AsOp()->gtGetOp2()->OperIsConst()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you introduce a function like IsProfitableToSetZeroFlag
and put this in there, and check it from the if above? Mainly in case more optimizations get added in the future which we would not want to skip for RSZ
.
Also, I think SupportsSettingZeroFlag
can work for all shifts and rotations and this profitability check should also happen for those (at the minimum this should also check GT_RSH
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jakobbotsch
Moved this logic to IsProfitableToSetZeroFlag function. Also, added several operations to SupportsSettingZeroFlag for future optimizations.
There are some cases in the diffs where the optimization is not kicking in: Can you check why? |
I just noticed that the above was a tier 0 method. It looks like |
* Add morphing for comparison between uint.MaxValue and a ulong value. * Remove assertions, which no longer is relevant. * Add a check to lsra to only use BMI2 if zero flag will not be set. * Add a profitability check to optimize EQ/NE(op, 0) only if op has constant operand.
907e97c
to
440adf9
Compare
bool Lowering::IsProfitableToSetZeroFlag(GenTree* op) const | ||
{ | ||
#ifdef TARGET_XARCH | ||
if (op->OperIs(GT_LSH, GT_RSH, GT_RSZ, GT_ROR)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've listed all ops that might set zero flag (GT_LSH, GT_RSH, GT_RSZ, GT_ROL, GT_ROR) in SupportsSettingZeroFlag, and filter it here to check if BMI2 version exists.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it missing GT_ROL
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I was able to search, there seems to be no operation for shift left on BMI2. So, I droped it from this if statement.
https://en.wikipedia.org/wiki/X86_instruction_listings
RORX reg,r/m,imm8 | VEX.LZ.F2.0F3A F0 /r ib | Rotate right by immediate without affecting flags. |
---|---|---|
SARX ra,r/m,rb | VEX.LZ.F3.0F38 F7 /r | Arithmetic shift right without updating flags.For SARX, SHRX and SHLX, the shift-amount specified in rb is masked to 5 bits for 32-bit operand size and 6 bits for 64-bit operand size. |
SHRX ra,r/m,rb | VEX.LZ.F2.0F38 F7 /r | Logical shift right without updating flags. |
SHLX ra,r/m,rb | VEX.LZ.66.0F38 F7 /r | Shift left without updating flags. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use rorx
for GT_ROL
under the same conditions we would use it for GT_ROR
.
runtime/src/coreclr/jit/codegenxarch.cpp
Lines 4905 to 4912 in cc2406f
// There is no 'rolx', so for rol, we use rorx with the shift value adjusted. | |
if (tree->OperIs(GT_ROL)) | |
{ | |
shiftByValue &= (size * BITS_PER_BYTE - 1); | |
shiftByValue = (size * BITS_PER_BYTE - shiftByValue); | |
} | |
inst_RV_TT_IV(INS_rorx, size, tree->GetRegNum(), operand, shiftByValue, INS_OPTS_NONE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for pointing this out. I'll put GT_ROL
to the criteria.
/azp run Fuzzlyn |
Azure Pipelines successfully started running 1 pipeline(s). |
Hi @jakobbotsch, I tried to review the Fuzzlyn results, but there are many errors that I’m having trouble interpreting. Sorry to bother you, but could you help me understand what they mean or guide me on how to proceed? Thanks in advance! |
I think the Fuzzlyn found issues are unrelated to this PR. I need to take another look, but I don't think anything more is needed from your side. |
Add morphing for comparison between uint.MaxValue and a ulong value.
Contribute to: #76525