8283598: [vectorapi] Add new vector operation for compress and expand bits #184
8283598: [vectorapi] Add new vector operation for compress and expand bits #184smita-kamath wants to merge 8 commits intoopenjdk:vectorIntrinsicsfrom
Conversation
|
👋 Welcome back svkamath! A progress list of the required criteria for merging this PR into |
Webrevs
|
| a = (byte) (a & bitmask); // Clear irrelevant bits | ||
| byte count_mask = (byte) (~bitmask << 1); // Count 0's to right | ||
|
|
||
| // Prefix mask identifies bits of bitmask that have odd number of 0's to the right | ||
| // Move mask identifies the bits to be moved | ||
| // temp identifies the bits of the given number to be moved | ||
| byte prefix_mask, move_mask, temp; | ||
| int iters = 3; | ||
|
|
||
| for (int i = 0; i < iters; i++) { | ||
| prefix_mask = (byte) (count_mask ^ (count_mask << 1)); // Parallel prefix | ||
| prefix_mask = (byte) (prefix_mask ^ (prefix_mask << 2)); | ||
| prefix_mask = (byte) (prefix_mask ^ (prefix_mask << 4)); | ||
| move_mask = (byte) (prefix_mask & bitmask); // Bits to move | ||
| bitmask = (byte)(bitmask ^ move_mask | (move_mask >> (1 << i))); // Compress bitmask | ||
| temp = (byte) (a & move_mask); // Bits of the number a to be moved. | ||
| a = (byte) (a ^ temp | (temp >> (1 << i))); // Compress a | ||
| count_mask = (byte) (count_mask & ~prefix_mask); // adjust count_mask by identifying bits that have 0 to the right | ||
| } |
There was a problem hiding this comment.
Hi @smita-kamath , can we simply count the bits number and then do a left shift on the result, e.g:
1) b = a & bitmask
2) b = popcount(b)
3) result = (0x1 << b) - 1
Please correct me if I misunderstood something. Thanks so much!
There was a problem hiding this comment.
@XiaohongGong The compression is based on the bits of bitmask, not on the bits of b, so bitcompress(0b1001, 0b1100) = 0b10, bitcompress(0b0101, 0b1011) = 0b001 (The number of bits in the result I write to be equal to the number of set bits in the mask for easier visualisation).
There was a problem hiding this comment.
Oh, I see, thanks for the explanation!
There was a problem hiding this comment.
So I think it's better to comment an example to the scalar method or API definition.
|
Hi, what do you think about adding this operation for scalar first, and then adding it to vector api later. We could add several other bit manipulation operations such as |
|
Hi @merykitty, That is a good idea. However, the effort to bring it to scalar is much larger as we need to file a JEP and follow the required processes. This is why we plan to introduce it in Vector API first. |
| /* Implementation note: The implementation is based on Compress or Generalized Extract mentioned in | ||
| * Henry S. Warren, Jr's Hackers Delight, Addison Wesley, 2002. | ||
| */ | ||
| static byte compressBits(byte a, byte bitmask) { |
There was a problem hiding this comment.
According to the 4th incubation(https://bugs.openjdk.java.net/browse/JDK-8280173), the compress bit should be similar to vector mask compress(CompressM). As per my understanding, the second argument bitmask should be the same as a. If so, it also can be removed.
There was a problem hiding this comment.
I think i mistook the intended implementation when writing the JEP.
Since there is no scalar equivalent the operation is currently under specified, and in this case I think the expand operation also makes sense so compress(expand(x, m), m) = x
There was a problem hiding this comment.
Just talked with @sviswa7. I will update the JEP. Also, i will follow up on scalar integral implementations for compress/expand bits, where the Byte/Short implementations defer to that on Integer. Intrinsic scalar implementations can be implemented afterwards.
There was a problem hiding this comment.
Hi @PaulSandoz, do you think this implementation of compress bits is fine? I can plan to create a separate PR for expand bits operation. Do let me know. Thanks.
There was a problem hiding this comment.
I think i mistook the intended implementation when writing the JEP.
Since there is no scalar equivalent the operation is currently under specified, and in this case I think the expand operation also makes sense so
compress(expand(x, m), m) = x
If the true count of m is less than the significant bits of x , I think x will lost bits so that this equation doesn't work. E.g., m = 0b00000001, x = 0b11111111. It's 0b00000001 after expand(x, m) , and if compressed it back with the same bitmask m, it will get 0b00000001.
There was a problem hiding this comment.
Yes, thanks, it only works for certain cases, i did not think it through carefully.
src/hotspot/share/opto/mulnode.hpp
Outdated
| // CompressBits placeholder node | ||
| class CompressBitsNode : public Node { | ||
| public: | ||
| CompressBitsNode( Node *in1, Node *in2 ) : Node(0,in1,in2) {} |
There was a problem hiding this comment.
Style: the spaces are not needed after "(" and before ")". And spaces are needed between the arguments. And "*" is better to be next close to the type. So suggest to modify as:
CompressBitsNode(Node* in1, Node* in2) : Node(0, in1, in2) {}
There was a problem hiding this comment.
Thank you. Will fix this.
| #end[long] | ||
| #end[intOrLong] | ||
| move_mask = ($type$) (prefix_mask & bitmask); // Bits to move | ||
| bitmask = ($type$)(bitmask ^ move_mask | (move_mask >> (1 << i))); // Compress bitmask |
There was a problem hiding this comment.
style: space between ($type$)(bitmask ^ move_mask | ...)
| #if[intOrLong] | ||
| #if[int] | ||
| int iters = 5; | ||
| #else[int] | ||
| int iters = 6; | ||
| #end[int] | ||
| #end[intOrLong] |
There was a problem hiding this comment.
why not simply with:
#if[int]
int iters = 5;
#end[int]
#if[long]
int iters = 6;
#end[long]
| #end[long] | ||
| #end[intOrLong] | ||
| move_mask = ($type$) (prefix_mask & b); | ||
| b = ($type$)(b ^ move_mask | (move_mask >> (1 << i))); |
There was a problem hiding this comment.
style: add one space between ($type$)(b ^ move_mask ...)
| $type$ prefix_mask, move_mask, temp; | ||
| a = ($type$) (a & b); | ||
| $type$ count_mask = ($type$) (~b << 1); | ||
| $type$ mp, mv, t; |
There was a problem hiding this comment.
Thanks for pointing this out. Will fix it.
| case T_BYTE: // Returning Op_CompressBits for | ||
| case T_SHORT:// all types temporarily. | ||
| case T_INT: | ||
| case T_LONG: return Op_CompressBits; | ||
| default: fatal("COMPRESS_BITS: %s", type2name(bt)); |
There was a problem hiding this comment.
The identity issue "three spaces before "case"". Seems the above bitcount and reverse have the same issue. So please fix them together. Thanks!
|
Here's the issue for scalar compress and expand bits JDK-8283892 |
Thanks for the update. That makes more sense to me now. |
There was a problem hiding this comment.
I recommend moving the scalar compress implementations out of the template and into say a new class CompressExpand, that will make it easier to replace later on. For the test code do something similar, place them in a separate class duplicating that in the vector API package (since the tests do not depend on internals of the API).
I started work on the scalar implementations here based on what you did, but tried to make the code more idiomatic, so maybe copy those? (Note these have yet to be be tested.)
|
@PaulSandoz, sounds good. Thank you. |
2) Added expand bits operation for int and long 3) Addressed review comments about code style 4) updated tests
|
@smita-kamath Please update the summary at the top of the PR to reflect the latest:
|
@sviswa7 , any specific reason to drop byte/short versions for these APIs |
|
@smita-kamath this pull request can not be integrated into git checkout compressbits
git fetch https://git.openjdk.java.net/panama-vector vectorIntrinsics
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge vectorIntrinsics"
git push |
|
@jatin-bhateja byte/short support for compress/expand were dropped from Vector API on advice from Paul Sandoz. |
| @@ -0,0 +1,8647 @@ | |||
| /* | |||
There was a problem hiding this comment.
This file should not be part of the commit, nor should perf_scalar_tests.template and perf_tests.template
| /* Implementation note: The implementation is based on Compress or Generalized Extract mentioned in | ||
| * Henry S. Warren, Jr's Hackers Delight, Addison Wesley, 2002. | ||
| */ | ||
| static $type$ compressBits($type$ a, $type$ mask) { |
There was a problem hiding this comment.
No need to make these part of the template. Copy from openjdk/jdk#8115 as Sandhya indicated and place them in a package private separate class, such as CompressExpand. Do the same for the tests and use directly. Then the code will be easier to replace.
2) Removed compressBits and expandBits 3) Created a separate test class 4) Updated template files
sviswa7
left a comment
There was a problem hiding this comment.
Rest of the patch looks good to me.
| return ($type$)((((($type$)a) & $Boxtype$.toUnsignedInt(($type$)-1)) >>> (n & $Boxtype$.SIZE-1)) | (((($type$)a) & $Boxtype$.toUnsignedInt(($type$)-1)) << ($Boxtype$.SIZE - (n & $Boxtype$.SIZE-1)))); | ||
| #end[intOrLong] | ||
| } | ||
|
|
There was a problem hiding this comment.
Extra empty line could be removed from template.
| #end[intOrLong] | ||
| } | ||
|
|
||
|
|
There was a problem hiding this comment.
Extra empty line could be removed from template.
|
@smita-kamath This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been no new commits pushed to the As you do not have Committer status in this project an existing Committer must agree to sponsor your change. Possible candidates are the reviewers of this PR (@PaulSandoz, @sviswa7) but any other Committer may sponsor as well. ➡️ To flag this PR as ready for integration with the above commit message, type |
| gen_binary_alu_op "COMPRESS_BITS" "CompressExpandTest.compress(a,b)" "intOrLong" | ||
| gen_binary_alu_op "EXPAND_BITS" "CompressExpandTest.expand(a,b)" "intOrLong" |
There was a problem hiding this comment.
| gen_binary_alu_op "COMPRESS_BITS" "CompressExpandTest.compress(a,b)" "intOrLong" | |
| gen_binary_alu_op "EXPAND_BITS" "CompressExpandTest.expand(a,b)" "intOrLong" | |
| gen_binary_alu_op "COMPRESS_BITS" "CompressExpandTest.compress(a, b)" "intOrLong" | |
| gen_binary_alu_op "EXPAND_BITS" "CompressExpandTest.expand(a, b)" "intOrLong" |
|
/integrate |
|
@smita-kamath |
|
/sponsor |
|
Going to push as commit 5fe7992. |
|
@sviswa7 @smita-kamath Pushed as commit 5fe7992. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
Hi,
I've added support for new vector operations for compressing bits of integral vector types(Byte/Short/Integer/Long).
The implementation is based on Compress or Generalized Extract mentioned in Hackers Delight by Henry S. Warren, Jr.
The implementation does the following: given a mask and the number to be compressed, the bits of the number corresponding to the set mask bit are selected and compressed.
Currently, this PR addresses only Java changes for compress bits operation. I've also updated the test framework.
Do review and share feedback.
Progress
Issue
Reviewers
Reviewing
Using
gitCheckout this PR locally:
$ git fetch https://git.openjdk.java.net/panama-vector pull/184/head:pull/184$ git checkout pull/184Update a local copy of the PR:
$ git checkout pull/184$ git pull https://git.openjdk.java.net/panama-vector pull/184/headUsing Skara CLI tools
Checkout this PR locally:
$ git pr checkout 184View PR using the GUI difftool:
$ git pr show -t 184Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/panama-vector/pull/184.diff