JDK-8374852: fix generate_limit_guard opaque handling and remove unneeded positive flag

This commit is contained in:
Damon Fenacci 2026-01-15 16:01:02 +01:00
parent d988b0f54c
commit e85784ae99
3 changed files with 12 additions and 16 deletions

View File

@ -899,7 +899,7 @@ inline Node* LibraryCallKit::generate_negative_guard(Node* index, RegionNode* re
Node* cmp_lt = _gvn.transform(new CmpINode(index, intcon(0)));
Node* bol_lt = _gvn.transform(new BoolNode(cmp_lt, BoolTest::lt));
if (is_opaque) {
bol_lt = _gvn.transform(new OpaqueGuardNode(C, bol_lt, false));
bol_lt = _gvn.transform(new OpaqueGuardNode(C, bol_lt));
}
Node* is_neg = generate_guard(bol_lt, region, PROB_MIN);
if (is_neg != nullptr && pos_index != nullptr) {
@ -940,7 +940,7 @@ inline Node* LibraryCallKit::generate_limit_guard(Node* offset,
Node* cmp_lt = _gvn.transform(new CmpUNode(array_length, last));
Node* bol_lt = _gvn.transform(new BoolNode(cmp_lt, BoolTest::lt));
if (is_opaque) {
bol_lt = _gvn.transform(new OpaqueGuardNode(C, bol_lt, true));
bol_lt = _gvn.transform(new OpaqueGuardNode(C, bol_lt));
}
Node* is_over = generate_guard(bol_lt, region, PROB_MIN);
return is_over;

View File

@ -2560,14 +2560,13 @@ void PhaseMacroExpand::eliminate_opaque_looplimit_macro_nodes() {
#endif
success = true;
} else if (n->is_OpaqueGuard()) {
// Tests with OpaqueGuard nodes are implicitly known to be true or false. Replace the node with appropriate
// value. In debug builds, we leave the test in the graph to have an additional sanity check at runtime. If
// the test fails (i.e. a bug), we will execute a Halt node.
// Tests with OpaqueGuard nodes are implicitly known to be false. Replace the node with false. In debug
// builds, we leave the test in the graph to have an additional sanity check at runtime. If the test
// fails (i.e. a bug), we will execute a Halt node.
#ifdef ASSERT
_igvn.replace_node(n, n->in(1));
#else
bool is_positive = n->as_OpaqueGuard()->is_positive();
_igvn.replace_node(n, _igvn.intcon(is_positive?1:0));
_igvn.replace_node(n, _igvn.intcon(0));
#endif
success = true;
} else if (n->is_OpaqueInitializedAssertionPredicate()) {

View File

@ -152,16 +152,14 @@ class OpaqueNotNullNode : public Node {
// (e.g. there is already a guard in the caller) but the compiler cannot prove it. We could in principle avoid
// adding a guard in the intrinsic but in some cases (e.g. when the input is a constant that breaks the guard
// and the caller guard is not inlined) the input of the intrinsic can become top and the data path is folded.
// Similar to OpaqueNotNullNode to ensure that the control path is also properly folded, we insert a
// OpaqueGuardNode before the If node in the guard. During macro expansion, we replace the OpaqueGuardNode with
// the corresponding constant (true/false) in product builds such that the actually unneeded guards
// are folded and do not end up in the emitted code. In debug builds, we keep the actual checks as additional
// verification code (i.e. removing OpaqueGuardNode and use the BoolNode inputs instead).
// Similar to OpaqueNotNullNode to ensure that the control path is also properly folded, we insert a OpaqueGuardNode
// before the If node in the guard. During macro expansion, we replace the OpaqueGuardNode with false in product
// builds such that the actually unneeded guards are folded and do not end up in the emitted code. In debug builds,
// we keep the actual checks as additional verification code (i.e. removing OpaqueGuardNode and use the BoolNode
// inputs instead).
class OpaqueGuardNode : public Node {
private:
bool _is_positive;
public:
OpaqueGuardNode(Compile* C, Node* tst, bool is_positive) : Node(nullptr, tst), _is_positive(is_positive) {
OpaqueGuardNode(Compile* C, Node* tst) : Node(nullptr, tst) {
init_class_id(Class_OpaqueGuard);
init_flags(Flag_is_macro);
C->add_macro_node(this);
@ -170,7 +168,6 @@ class OpaqueGuardNode : public Node {
virtual int Opcode() const;
virtual const Type* Value(PhaseGVN* phase) const;
virtual const Type* bottom_type() const { return TypeInt::BOOL; }
bool is_positive() const { return _is_positive; }
};
// This node is used for Template Assertion Predicate BoolNodes. A Template Assertion Predicate is always removed