Skip to content

Commit

Permalink
Apply fix for JDK-8316105
Browse files Browse the repository at this point in the history
  • Loading branch information
chhagedorn committed Sep 21, 2023
1 parent 71fe2f6 commit cee30fc
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 36 deletions.
4 changes: 0 additions & 4 deletions src/hotspot/share/opto/loopTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2569,10 +2569,6 @@ void PhaseIdealLoop::do_range_check(IdealLoopTree *loop, Node_List &old_new) {
// The underflow and overflow limits: 0 <= scale*I+offset < limit
add_constraint(stride_con, lscale_con, offset, zero, limit, pre_ctrl, &pre_limit, &main_limit);
loop_entry = add_range_check_elimination_assertion_predicates(loop, scale_con, int_offset, int_limit);

// Add two Template Assertion Predicates to create new Initialized Assertion Predicates from when either
// unrolling or splitting this main-loop further.

} else {
if (PrintOpto) {
tty->print_cr("missed RCE opportunity");
Expand Down
61 changes: 33 additions & 28 deletions src/hotspot/share/opto/predicates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,12 @@ class ParsePredicateUsefulMarker : public PredicateVisitor {
}
};

// Mark all Parse Predicates 'loop' as useful. If 'loop' represents an outer strip mined loop, we can skip it because
// we have already processed the predicates before when we visited its counted (inner) loop.
void EliminateUselessParsePredicates::mark_parse_predicates_useful(IdealLoopTree* loop) {
if (loop->can_apply_loop_predication()) {
if (loop->can_apply_loop_predication() && !loop->_head->is_OuterStripMinedLoop()) {
ParsePredicateUsefulMarker useful_marker;
Node* entry = loop->_head->in(LoopNode::EntryControl);
Node* entry = loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl);
PredicatesForLoop predicates_for_loop(entry, &useful_marker);
predicates_for_loop.for_each();
}
Expand Down Expand Up @@ -852,14 +854,14 @@ bool InitializedAssertionPredicate::has_halt(const Node* success_proj) {

#ifdef ASSERT
// Check that the block has at most one Parse Predicate and that we only find Regular Predicate nodes (i.e. IfProj,
// If, or RangeCheck nodes).
// If, RangeCheck, or TemplateAssertionPredicate nodes.
void PredicateBlock::verify_block() {
Node* next = _parse_predicate.entry(); // Skip unique Parse Predicate of this block if present
while (next != _entry) {
assert(!next->is_ParsePredicate(), "can only have one Parse Predicate in a block");
const int opcode = next->Opcode();
assert(next->is_IfProj() || opcode == Op_If || opcode == Op_RangeCheck,
"Regular Predicates consist of an IfProj and an If or RangeCheck node");
assert(next->is_IfProj() || next->is_TemplateAssertionPredicate() || opcode == Op_If || opcode == Op_RangeCheck,
"Regular Predicates consist of an IfProj and an If or RangeCheck or a TemplateAssertionPredicate node");
next = next->in(0);
}
}
Expand All @@ -869,30 +871,33 @@ void PredicateBlock::verify_block() {
// anymore (i.e. entry to the first Regular Predicate in this block if any or `regular_predicate_proj` otherwise).
Node* PredicateBlock::skip_regular_predicates(Node* regular_predicate_proj, Deoptimization::DeoptReason deopt_reason) {
PredicateVisitor do_nothing_visitor;
BlockPredicateIterator block_predicate_iterator(regular_predicate_proj, deopt_reason, &do_nothing_visitor);
return block_predicate_iterator.for_each();
PredicateInBlockIterator predicate_in_block_iterator(regular_predicate_proj, deopt_reason, &do_nothing_visitor);
return predicate_in_block_iterator.for_each();
}

BlockPredicateIterator::BlockPredicateIterator(Node* start_node, Deoptimization::DeoptReason deopt_reason,
PredicateVisitor* predicate_visitor)
: _deopt_reason(deopt_reason),
_start_node(start_node),
_predicate_visitor(predicate_visitor) {}
// Applies the PredicateVisitor to each Regular Predicate in this block.
Node* PredicateInBlockIterator::for_each() {
Node* entry = _start_node;
if (entry->is_IfTrue() && entry->in(0)->is_ParsePredicate()) {
ParsePredicate parse_predicate(entry, _deopt_reason);
if (parse_predicate.is_valid()) {
_predicate_visitor->visit(parse_predicate);
entry = parse_predicate.entry();
} else {
// Parse Predicate belonging to a different Predicate Block.
return entry;
}
}

// Applies the PredicateVisitor to each predicate in this block.
Node* BlockPredicateIterator::for_each() {
RegularPredicateInBlockIterator regular_predicate_in_block_iterator(entry, _deopt_reason, _predicate_visitor);
return regular_predicate_in_block_iterator.for_each();
}

// Applies the PredicateVisitor to each Regular Predicate in this block.
Node* RegularPredicateInBlockIterator::for_each() {
Node* entry = _start_node;
while (true) {
if (entry->is_IfTrue() && entry->in(0)->is_ParsePredicate()) {
ParsePredicate parse_predicate(entry, _deopt_reason);
if (parse_predicate.is_valid()) {
_predicate_visitor->visit(parse_predicate);
entry = parse_predicate.entry();
} else {
// Parse Predicate belonging to a different Predicate Block.
break;
}
} else if (entry->is_TemplateAssertionPredicate()) {
if (entry->is_TemplateAssertionPredicate()) {
TemplateAssertionPredicate template_assertion_predicate(entry->as_TemplateAssertionPredicate());
_predicate_visitor->visit(template_assertion_predicate);
entry = template_assertion_predicate.entry();
Expand All @@ -905,7 +910,7 @@ Node* BlockPredicateIterator::for_each() {
_predicate_visitor->visit(initialized_assertion_predicate);
entry = initialized_assertion_predicate.entry();
} else {
// Not a Regular Predicate.
// Either a Parse Predicate or not a Regular Predicate. In both cases, the node does not belong to this block.
break;
}
}
Expand All @@ -925,14 +930,14 @@ void PredicatesForLoop::for_each() {
}

Node* PredicatesForLoop::for_each(Node* current, Deoptimization::DeoptReason deopt_reason) {
BlockPredicateIterator block_predicate_iterator(current, deopt_reason, _predicate_visitor);
return block_predicate_iterator.for_each();
PredicateInBlockIterator predicate_in_block_iterator(current, deopt_reason, _predicate_visitor);
return predicate_in_block_iterator.for_each();
}

PredicateEntryIterator::PredicateEntryIterator(Node* start)
: _current(start) {}

// Is current node pointed at by iterator a predicate?
// Is current node pointed at by iterator a predicate tail?
bool PredicateEntryIterator::has_next() const {
if (_current->is_TemplateAssertionPredicate()) {
return true;
Expand Down
26 changes: 22 additions & 4 deletions src/hotspot/share/opto/predicates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -728,15 +728,33 @@ class Predicates : public StackObj {
}
};

// Predicate Block iterator that applies a PredicateVisitor to each predicate in the block specified by the deopt_reason
// and starting at the passed node.
class BlockPredicateIterator : public StackObj {
// Iterator that applies a PredicateVisitor to each Regular Predicate in the block specified by the deopt_reason.
class RegularPredicateInBlockIterator : public StackObj {
Deoptimization::DeoptReason _deopt_reason;
Node* _start_node;
PredicateVisitor* _predicate_visitor;

public:
BlockPredicateIterator(Node* start_node, Deoptimization::DeoptReason deopt_reason, PredicateVisitor* predicate_visitor);
RegularPredicateInBlockIterator(Node* start_node, Deoptimization::DeoptReason deopt_reason,
PredicateVisitor* predicate_visitor)
: _deopt_reason(deopt_reason),
_start_node(start_node),
_predicate_visitor(predicate_visitor) {}

Node* for_each();
};

// Iterator that applies a PredicateVisitor to each predicate in the block specified by the deopt_reason.
class PredicateInBlockIterator : public StackObj {
Node* _start_node;
Deoptimization::DeoptReason _deopt_reason;
PredicateVisitor* _predicate_visitor;

public:
PredicateInBlockIterator(Node* start_node, Deoptimization::DeoptReason deopt_reason, PredicateVisitor* predicate_visitor)
: _start_node(start_node),
_deopt_reason(deopt_reason),
_predicate_visitor(predicate_visitor) {}

Node* for_each();
};
Expand Down

0 comments on commit cee30fc

Please sign in to comment.