-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
8319822: Use a linear-time algorithm for assert_different_registers() #16617
Conversation
👋 Welcome back aph! A progress list of the required criteria for merging this PR into |
@theRealAph The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
The build fails on Windows:
|
Argh! Thanks. |
I started to review the patch and was wondering if this could be simplify to something like this?: I tested this with this small section of temporary static_asserts: Unfortunately, that didn't compile and I had make this change to get it to work: |
Sure, it could be done. This is a minor efficiency tweak. |
I ran into a case where I was doing assert_different_registers() on base() and index() from an Address. How hard would it be to have assert_different_registers() support an Address as an argument? |
I'm afraid the compiler warnings on Windows still exist. See the GHA test results. |
Quite tricky, partly because |
It tested the build performance before this PR, with the patch in this PR, and my simplified version. I can't see any performance difference on my MacBook M1. Is there any platform where this makes a bigger difference? Edit: I realize that since this doesn't always boil down to a constexpr, then the run time might be more interesting than the build time. |
From the summary:
As mentioned in #16617 (comment) this doesn't work unless we make the proposed small tweak. Do you want to make it in this PR, or should I propose that in a separate PR? |
I don't think you'll be able to measure such a tiny difference in build performance, especially given all the other thiungs that are going on, and especially on a Great Big Out-Of-Order machine. But at runtime, the three-operand check can be performed with just three comparisons. I'm not fixated on this, though, and I can take the special cases out. |
Done, thanks and sorry for the delay. |
@theRealAph This pull request has been inactive for more than 4 weeks and will be automatically closed if another 4 weeks passes without any activity. To avoid this, simply add a new comment to the pull request. Feel free to ask for assistance if you need help with progressing this pull request towards integration! |
Let's do it separately. I would, but GCC has a very relaxed attitude to |
Exhuming this one after a long time. Please review, thanks. |
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.
Approved. I've written some suggestions that I would prefer, but that are not strictly necessary before integration.
You won't see very much, if any, because other things dominate. The main advantage, going forward, is that much of this can be constexpr'd, once I find out how to test on Windows. |
Co-authored-by: Stefan Karlsson <stefan.karlsson@oracle.com>
src/hotspot/cpu/x86/register_x86.hpp
Outdated
uint32_t first = _bitset & -_bitset; | ||
return first ? as_Register(exact_log2(first)) : noreg; | ||
size_t first = _bitset & -_bitset; | ||
return first != 0 ? as_Register(exact_log2(first)) : noreg; |
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.
This could instead be
if (_bitset == 0) { return noreg; }
return as_register(count_trailing_zeros(_bitset));
which would be consistent with how last
is being calculated. Note that exact_log2 bottoms
out in count_trailing_zeros.
Similarly for the XMMRegister case below.
src/hotspot/share/asm/register.hpp
Outdated
@@ -245,14 +253,44 @@ inline ReverseRegSetIterator<RegImpl> AbstractRegSet<RegImpl>::rbegin() { | |||
|
|||
// Debugging support | |||
|
|||
template<typename R, typename... Rx> | |||
inline constexpr bool different_registers(AbstractRegSet<R> allocated_regs, R first_register) { |
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.
Good point about static_assert. Don't make it debug-only.
src/hotspot/share/asm/register.hpp
Outdated
@@ -245,14 +253,35 @@ inline ReverseRegSetIterator<RegImpl> AbstractRegSet<RegImpl>::rbegin() { | |||
|
|||
// Debugging support | |||
|
|||
template<typename R, typename... Rx> |
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.
Rx is unused.
src/hotspot/share/asm/register.hpp
Outdated
@@ -245,14 +253,44 @@ inline ReverseRegSetIterator<RegImpl> AbstractRegSet<RegImpl>::rbegin() { | |||
|
|||
// Debugging support | |||
|
|||
template<typename R, typename... Rx> | |||
inline constexpr bool different_registers(AbstractRegSet<R> allocated_regs, R first_register) { |
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.
"inline" is still redundant with "constexpr".
I have no idea, really. assert_different_registers is used all over the place, and I'm going for bootcycle and tier1. |
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.
Looks good.
You could write a death test gtest. Like this:
|
I could, but I don't think there's much 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 could, but I don't think there's much point. assert_different_registers() is used so much that it'll get thoroughly tested in the positive cases, at least. Do you think this is important?
See my remarks. I am mainly concerned about exceeding the range for the bit set. If you add the proposed static assert, I think we are good.
src/hotspot/share/asm/register.hpp
Outdated
@@ -93,67 +93,75 @@ template <class RegImpl> class ReverseRegSetIterator; | |||
// A set of registers | |||
template <class RegImpl> | |||
class AbstractRegSet { | |||
uint32_t _bitset; | |||
size_t _bitset; |
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.
Why couple the number of possible registers to the memory size? Why not uint64_t?
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.
64-bit makes sense.
I think this may have been broken for ppc where the number of vector registers can exceed 32 (
jdk/src/hotspot/cpu/ppc/register_ppc.hpp
Line 378 in 91101f0
number_of_registers = 64 |
Unless I am mistaken, assert_different_registers
, if applied to VSR32 and up, would never have fired.
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.
OK, I get it. I was sort-of thinking that on the 32-bit platforms we support we don't ever have more than 32 registers in a set, but maybe that's not true. I certainly don't want to slow down 32-bit platforms by burdening them with double-word operations for something that can never happen.
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.
Okay. Well, if we have a static assert, we will notice if we have more registers than fit the bitset.
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.
So I'm getting this bizarre failure on arm32. I'm guessing it's actually a compiler bug, but I suppose it might be some dusty corner of C++ to do with template arg substitution. Any thoughts?
In file included from /home/runner/work/jdk/jdk/src/hotspot/share/utilities/globalDefinitions.hpp:29,
from /home/runner/work/jdk/jdk/src/hotspot/share/nmt/memflags.hpp:28,
from /home/runner/work/jdk/jdk/src/hotspot/share/memory/allocation.hpp:29,
from ad_arm.hpp:30,
from ad_arm.cpp:28:
/home/runner/work/jdk/jdk/src/hotspot/share/asm/register.hpp: In instantiation of ‘class AbstractRegSet<RegisterImpl*>’:
/home/runner/work/jdk/jdk/src/hotspot/share/asm/register.hpp:272:30: required from ‘constexpr bool different_registers(R, Rx ...) [with R = RegisterImpl*; Rx = {RegisterImpl*, RegisterImpl*}]’
/home/runner/work/jdk/jdk/src/hotspot/share/asm/register.hpp:278:27: required from ‘void assert_different_registers(R, Rx ...) [with R = RegisterImpl*; Rx = {RegisterImpl*, RegisterImpl*}]’
/home/runner/work/jdk/jdk/src/hotspot/cpu/arm/arm.ad:8984:52: required from here
/home/runner/work/jdk/jdk/src/hotspot/share/asm/register.hpp:96:26: error: ‘number_of_registers’ is not a member of ‘RegisterImpl*’
96 | STATIC_ASSERT(RegImpl::number_of_registers <= 64);
| ^~~~~~~~~~~~~~~~~~~
/home/runner/work/jdk/jdk/src/hotspot/share/utilities/debug.hpp:287:44: note: in definition of macro ‘STATIC_ASSERT’
287 | #define STATIC_ASSERT(Cond) static_assert((Cond), #Cond)
| ^~~~
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.
BTW Would the runtime assert not prevent this from used as constexpr?
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.
It doesn't, and I just saw the problem: on Arm, Register
is a pointer type, whereas on other ports it's a class type.
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.
Looks like our comments crossed over. I'm building Zero and it's OK so far.
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 guess Arm never got converted. That port needs some love.
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.
Or, deprecation.
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.
Looks good to me. Thanks for working in my remarks.
@@ -68,6 +68,8 @@ | |||
|
|||
#include <sys/types.h> | |||
|
|||
static_assert(different_registers(zr, sp), "fucked"); |
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.
Debugging remnant?
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.
Ah, LOL! :-)
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.
Still looks good.
/integrate |
Going to push as commit 9b3694c.
Your commit was automatically rebased without conflicts. |
@theRealAph Pushed as commit 9b3694c. 💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored. |
At the present time,
assert_different_registers()
uses an O(N**2) algorithm in assert_different_registers(). We can utilize RegSet to do it in O(N) time. This would be a useful optimization for all builds with assertions enabled.In addition, it would be useful to be able to static_assert different registers.
Also, I've taken the opportunity to expand the maximum size of a RegSet to 64 on 64-bit platforms.
I also fixed a bug: sometimes
noreg
is passed toassert_different_registers()
, but it may only be passed once or a spurious assertion is triggered.Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk.git pull/16617/head:pull/16617
$ git checkout pull/16617
Update a local copy of the PR:
$ git checkout pull/16617
$ git pull https://git.openjdk.org/jdk.git pull/16617/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 16617
View PR using the GUI difftool:
$ git pr show -t 16617
Using diff file
Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/16617.diff
Webrev
Link to Webrev Comment