Skip to content

Commit decb1b7

Browse files
committed
8286800: Assert in PhaseIdealLoop::dump_real_LCA is too strong
Reviewed-by: kvn, rcastanedalo
1 parent c49e484 commit decb1b7

File tree

2 files changed

+105
-75
lines changed

2 files changed

+105
-75
lines changed

src/hotspot/share/opto/loopnode.cpp

Lines changed: 100 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -6012,80 +6012,88 @@ void PhaseIdealLoop::dump_bad_graph(const char* msg, Node* n, Node* early, Node*
60126012
}
60136013
}
60146014
}
6015-
tty->cr();
6016-
tty->print_cr("idoms of early %d:", early->_idx);
6017-
dump_idom(early);
6018-
tty->cr();
6019-
tty->print_cr("idoms of (wrong) LCA %d:", LCA->_idx);
6020-
dump_idom(LCA);
6021-
tty->cr();
6022-
dump_real_LCA(early, LCA);
6015+
dump_idoms(early, LCA);
60236016
tty->cr();
60246017
}
60256018

6026-
// Find the real LCA of early and the wrongly assumed LCA.
6027-
void PhaseIdealLoop::dump_real_LCA(Node* early, Node* wrong_lca) {
6028-
assert(!is_dominator(early, wrong_lca) && !is_dominator(early, wrong_lca),
6029-
"sanity check that one node does not dominate the other");
6030-
assert(!has_ctrl(early) && !has_ctrl(wrong_lca), "sanity check, no data nodes");
6019+
// Class to compute the real LCA given an early node and a wrong LCA in a bad graph.
6020+
class RealLCA {
6021+
const PhaseIdealLoop* _phase;
6022+
Node* _early;
6023+
Node* _wrong_lca;
6024+
uint _early_index;
6025+
int _wrong_lca_index;
6026+
6027+
// Given idom chains of early and wrong LCA: Walk through idoms starting at StartNode and find the first node which
6028+
// is different: Return the previously visited node which must be the real LCA.
6029+
// The node lists also contain _early and _wrong_lca, respectively.
6030+
Node* find_real_lca(Unique_Node_List& early_with_idoms, Unique_Node_List& wrong_lca_with_idoms) {
6031+
int early_index = early_with_idoms.size() - 1;
6032+
int wrong_lca_index = wrong_lca_with_idoms.size() - 1;
6033+
bool found_difference = false;
6034+
do {
6035+
if (early_with_idoms[early_index] != wrong_lca_with_idoms[wrong_lca_index]) {
6036+
// First time early and wrong LCA idoms differ. Real LCA must be at the previous index.
6037+
found_difference = true;
6038+
break;
6039+
}
6040+
early_index--;
6041+
wrong_lca_index--;
6042+
} while (wrong_lca_index >= 0);
60316043

6032-
ResourceMark rm;
6033-
Node_List nodes_seen;
6034-
Node* real_LCA = NULL;
6035-
Node* n1 = wrong_lca;
6036-
Node* n2 = early;
6037-
uint count_1 = 0;
6038-
uint count_2 = 0;
6039-
// Add early and wrong_lca to simplify calculation of idom indices
6040-
nodes_seen.push(n1);
6041-
nodes_seen.push(n2);
6042-
6043-
// Walk the idom chain up from early and wrong_lca and stop when they intersect.
6044-
while (!n1->is_Start() && !n2->is_Start()) {
6045-
n1 = idom(n1);
6046-
n2 = idom(n2);
6047-
if (n1 == n2) {
6048-
// Both idom chains intersect at the same index
6049-
real_LCA = n1;
6050-
count_1 = nodes_seen.size() / 2;
6051-
count_2 = count_1;
6052-
break;
6053-
}
6054-
if (check_idom_chains_intersection(n1, count_1, count_2, &nodes_seen)) {
6055-
real_LCA = n1;
6056-
break;
6057-
}
6058-
if (check_idom_chains_intersection(n2, count_2, count_1, &nodes_seen)) {
6059-
real_LCA = n2;
6060-
break;
6061-
}
6062-
nodes_seen.push(n1);
6063-
nodes_seen.push(n2);
6044+
assert(early_index >= 0, "must always find an LCA - cannot be early");
6045+
_early_index = early_index;
6046+
_wrong_lca_index = wrong_lca_index;
6047+
Node* real_lca = early_with_idoms[_early_index + 1]; // Plus one to skip _early.
6048+
assert(found_difference || real_lca == _wrong_lca, "wrong LCA dominates early and is therefore the real LCA");
6049+
return real_lca;
60646050
}
60656051

6066-
assert(real_LCA != NULL, "must always find an LCA");
6067-
tty->print_cr("Real LCA of early %d (idom[%d]) and (wrong) LCA %d (idom[%d]):", early->_idx, count_2, wrong_lca->_idx, count_1);
6068-
real_LCA->dump();
6069-
}
6052+
void dump(Node* real_lca) {
6053+
tty->cr();
6054+
tty->print_cr("idoms of early \"%d %s\":", _early->_idx, _early->Name());
6055+
_phase->dump_idom(_early, _early_index + 1);
60706056

6071-
// Check if n is already on nodes_seen (i.e. idom chains of early and wrong_lca intersect at n). Determine the idom index of n
6072-
// on both idom chains and return them in idom_idx_new and idom_idx_other, respectively.
6073-
bool PhaseIdealLoop::check_idom_chains_intersection(const Node* n, uint& idom_idx_new, uint& idom_idx_other, const Node_List* nodes_seen) const {
6074-
if (nodes_seen->contains(n)) {
6075-
// The idom chain has just discovered n.
6076-
// Divide by 2 because nodes_seen contains the same amount of nodes from both chains.
6077-
idom_idx_new = nodes_seen->size() / 2;
6078-
6079-
// The other chain already contained n. Search the index.
6080-
for (uint i = 0; i < nodes_seen->size(); i++) {
6081-
if (nodes_seen->at(i) == n) {
6082-
// Divide by 2 because nodes_seen contains the same amount of nodes from both chains.
6083-
idom_idx_other = i / 2;
6084-
}
6057+
tty->cr();
6058+
tty->print_cr("idoms of (wrong) LCA \"%d %s\":", _wrong_lca->_idx, _wrong_lca->Name());
6059+
_phase->dump_idom(_wrong_lca, _wrong_lca_index + 1);
6060+
6061+
tty->cr();
6062+
tty->print("Real LCA of early \"%d %s\" (idom[%d]) and wrong LCA \"%d %s\"",
6063+
_early->_idx, _early->Name(), _early_index, _wrong_lca->_idx, _wrong_lca->Name());
6064+
if (_wrong_lca_index >= 0) {
6065+
tty->print(" (idom[%d])", _wrong_lca_index);
60856066
}
6086-
return true;
6067+
tty->print_cr(":");
6068+
real_lca->dump();
60876069
}
6088-
return false;
6070+
6071+
public:
6072+
RealLCA(const PhaseIdealLoop* phase, Node* early, Node* wrong_lca)
6073+
: _phase(phase), _early(early), _wrong_lca(wrong_lca), _early_index(0), _wrong_lca_index(0) {
6074+
assert(!wrong_lca->is_Start(), "StartNode is always a common dominator");
6075+
}
6076+
6077+
void compute_and_dump() {
6078+
ResourceMark rm;
6079+
Unique_Node_List early_with_idoms;
6080+
Unique_Node_List wrong_lca_with_idoms;
6081+
early_with_idoms.push(_early);
6082+
wrong_lca_with_idoms.push(_wrong_lca);
6083+
_phase->get_idoms(_early, 10000, early_with_idoms);
6084+
_phase->get_idoms(_wrong_lca, 10000, wrong_lca_with_idoms);
6085+
Node* real_lca = find_real_lca(early_with_idoms, wrong_lca_with_idoms);
6086+
dump(real_lca);
6087+
}
6088+
};
6089+
6090+
// Dump the idom chain of early, of the wrong LCA and dump the real LCA of early and wrong LCA.
6091+
void PhaseIdealLoop::dump_idoms(Node* early, Node* wrong_lca) {
6092+
assert(!is_dominator(early, wrong_lca), "sanity check that early does not dominate wrong lca");
6093+
assert(!has_ctrl(early) && !has_ctrl(wrong_lca), "sanity check, no data nodes");
6094+
6095+
RealLCA real_lca(this, early, wrong_lca);
6096+
real_lca.compute_and_dump();
60896097
}
60906098
#endif // ASSERT
60916099

@@ -6158,16 +6166,38 @@ void PhaseIdealLoop::dump(IdealLoopTree* loop, uint idx, Node_List &rpo_list) co
61586166
}
61596167
}
61606168

6161-
void PhaseIdealLoop::dump_idom(Node* n) const {
6169+
void PhaseIdealLoop::dump_idom(Node* n, const uint count) const {
61626170
if (has_ctrl(n)) {
61636171
tty->print_cr("No idom for data nodes");
61646172
} else {
6165-
for (int i = 0; i < 100 && !n->is_Start(); i++) {
6166-
tty->print("idom[%d] ", i);
6167-
n->dump();
6168-
n = idom(n);
6173+
ResourceMark rm;
6174+
Unique_Node_List idoms;
6175+
get_idoms(n, count, idoms);
6176+
dump_idoms_in_reverse(n, idoms);
6177+
}
6178+
}
6179+
6180+
void PhaseIdealLoop::get_idoms(Node* n, const uint count, Unique_Node_List& idoms) const {
6181+
Node* next = n;
6182+
for (uint i = 0; !next->is_Start() && i < count; i++) {
6183+
next = idom(next);
6184+
assert(!idoms.member(next), "duplicated idom is not possible");
6185+
idoms.push(next);
6186+
}
6187+
}
6188+
6189+
void PhaseIdealLoop::dump_idoms_in_reverse(const Node* n, const Node_List& idom_list) const {
6190+
Node* next;
6191+
uint padding = 3;
6192+
uint node_index_padding_width = static_cast<int>(log10(C->unique())) + 1;
6193+
for (int i = idom_list.size() - 1; i >= 0; i--) {
6194+
if (i == 9 || i == 99) {
6195+
padding++;
61696196
}
6197+
next = idom_list[i];
6198+
tty->print_cr("idom[%d]:%*c%*d %s", i, padding, ' ', node_index_padding_width, next->_idx, next->Name());
61706199
}
6200+
tty->print_cr("n: %*c%*d %s", padding, ' ', node_index_padding_width, n->_idx, n->Name());
61716201
}
61726202
#endif // NOT PRODUCT
61736203

src/hotspot/share/opto/loopnode.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,10 +1656,8 @@ class PhaseIdealLoop : public PhaseTransform {
16561656
static void check_created_predicate_for_unswitching(const Node* new_entry) PRODUCT_RETURN;
16571657

16581658
bool _created_loop_node;
1659-
#ifdef ASSERT
1660-
void dump_real_LCA(Node* early, Node* wrong_lca);
1661-
bool check_idom_chains_intersection(const Node* n, uint& idom_idx_new, uint& idom_idx_other, const Node_List* nodes_seen) const;
1662-
#endif
1659+
DEBUG_ONLY(void dump_idoms(Node* early, Node* wrong_lca);)
1660+
NOT_PRODUCT(void dump_idoms_in_reverse(const Node* n, const Node_List& idom_list) const;)
16631661

16641662
public:
16651663
void set_created_loop_node() { _created_loop_node = true; }
@@ -1672,7 +1670,9 @@ class PhaseIdealLoop : public PhaseTransform {
16721670

16731671
#ifndef PRODUCT
16741672
void dump() const;
1675-
void dump_idom(Node* n) const;
1673+
void dump_idom(Node* n) const { dump_idom(n, 1000); } // For debugging
1674+
void dump_idom(Node* n, uint count) const;
1675+
void get_idoms(Node* n, uint count, Unique_Node_List& idoms) const;
16761676
void dump(IdealLoopTree* loop, uint rpo_idx, Node_List &rpo_list) const;
16771677
void verify() const; // Major slow :-)
16781678
void verify_compare(Node* n, const PhaseIdealLoop* loop_verify, VectorSet &visited) const;

0 commit comments

Comments
 (0)