-
Notifications
You must be signed in to change notification settings - Fork 740
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
Accelerate StringCoding.hasNegatives for JDK 11, 17, StringCoding.countPositives for JDK 21+ on x86 #21121
base: master
Are you sure you want to change the base?
Accelerate StringCoding.hasNegatives for JDK 11, 17, StringCoding.countPositives for JDK 21+ on x86 #21121
Conversation
Paging @vijaysun-omr, @0xdaryl for review and @r30shah, @dchopra001 as requested for comparison to acceleration on Z |
543b8ac
to
233cf24
Compare
Looks fine to me from a quick review. I'll probably defer to @hzongaro for the review since he has much more direct awareness of this work than I do, and can easily review the inliner parts as well (that I skimmed over too). |
It appears that the crash is due to a recent OMR commit and is therefore unrelated to my changes. I can build successfully with the |
generateRegRegInstruction(TR::InstOpCode::PTESTRegReg, node, xmmchunk, xmmmask, cg); | ||
|
||
// If the result is nonzero (i.e. at least one of the sign bits is set), break and return index | ||
generateLabelInstruction(TR::InstOpCode::JNE4, node, returnIndexLabel, cg); |
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.
at least one of the sign bits is set
Don't you need to keep track of the index of last positive element? This function should find the number of leading positive elements so the location of that negative matters. You cannot return (i - off) as you do in the residue processing because you don't know where in the vector the first negative is.
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.
The key here was pointed out by Henry early on when I was first trying to figure out how to accelerate countPositives
:
/**
* Count the number of leading positive bytes in the range.
*
* @implSpec the implementation must return len if there are no negative
* bytes in the range. If there are negative bytes, the implementation must return
* a value that is less than or equal to the index of the first negative byte
* in the range.
*/
countPositives
only needs to return a value less than or equal to the index of the first negative byte. There are a few places in String.java
that call countPositives
and then do the work of finding the exact index themselves. I suppose the reason it was designed this way is to take advantage of small time saves in situations where you don't care about the exact index (like when being called by hasNegatives
).
|
||
case TR::java_lang_StringCoding_countPositives: | ||
{ | ||
if (comp->target().cpu.supportsFeature(OMR_FEATURE_X86_SSE2) && feGetEnv("replaceCountPositives") != NULL) |
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.
You already called cg->setSupportsInlineStringCodingCountPositives()
so you should be calling cg->getSupportsInlineStringCodingCountPositives()
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 consolidated all of the inlining logic into InlinerTempForJ9
, since I was already using it to conditionally only inline countPositives
into hasNegatives
. I've confirmed that the inlining behaviour is still correct using this method.
8e367bc
to
c31a888
Compare
I fixed the bug! I squashed all of my review comment changes into one commit, just doing some more performance testing |
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.
Great work! I just have a few suggestions/comments
// return_false label | ||
generateLabelInstruction(TR::InstOpCode::label, node, returnFalseLabel, cg); | ||
|
||
// result = 0 | ||
generateRegImmInstruction(TR::InstOpCode::MOV8RegImm4, node, resultReg, 0, cg); |
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.
Instead of having a falseLabel
where resultReg
is set to zero, I wonder whether it would be better to set resultReg
to zero at the start of the inline code sequence. Then this end sequence would only need to handle the returnTrueLabel
case:
returnTrueLabel:
resultReg = 1
endLabel:
and the if bytes_left == 0
above could branch directly to endLabel
.
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 chose to implement your other suggestion in #21121 (comment) instead, since I combined inlineHasNegatives
and inlineCountPositives
and had to choose one.
generateRegRegInstruction(TR::InstOpCode::MOV8RegReg, node, indexReg, offsetReg, cg); | ||
|
||
// limit = offset + length | ||
generateRegRegInstruction(TR::InstOpCode::MOV8RegReg, node, limitReg, offsetReg, cg); |
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.
You still have added offset before ANDing:
loopLimit = ((off + length) & -16) + off
It should be as follows:
loopLimit = (length & -16) + off
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.
Hi Brad, I might confused, but I don't think I'm adding offset before ANDing?
// loopLimit = (length & -16) + offset
generateRegRegInstruction(TR::InstOpCode::MOV4RegReg, node, loopLimitReg, lengthReg, cg);
generateRegImmInstruction(TR::InstOpCode::AND4RegImm4, node, loopLimitReg, -16, cg);
generateRegRegInstruction(TR::InstOpCode::ADD4RegReg, node, loopLimitReg, offsetReg, cg);
c31a888
to
ba61f0c
Compare
@0xdaryl I believe I am ready for your review whenever you are! |
This PR accelerates intrinsic candidates
StringCoding.hasNegatives
andStringCoding.countPositives
on x86, the former on JDK 9-18 and the latter on JDK 19+.This PR is incremental in a few ways.
hasNegatives
for arrays of 0-8 elements on JDK 19+. It performs so well for these short arrays that implementing my 'acceleration' would actually cause a performance regression there. While this anomaly is investigated, I will not be acceleratinghasNegatives
on JDK 19+.In the interest of taking advantage of the performance boost as it currently stands for the 0.51 release, this PR will deliver these changes in their incremental state, with plans for another PR or two down the road to close the aforementioned gaps.