Skip to content

Commit e879f8c

Browse files
committed
8265587: IGV: track nodes across matching
Preserve the IGV node identifier of Ideal nodes in their corresponding machine nodes after matching, to allow IGV users to track nodes across this phase. Reviewed-by: thartmann, vlivanov
1 parent 164454f commit e879f8c

File tree

4 files changed

+37
-30
lines changed

4 files changed

+37
-30
lines changed

src/hotspot/share/opto/idealGraphPrinter.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -450,13 +450,10 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
450450
} else {
451451
print_prop("is_dontcare", "false");
452452
}
453-
454-
#ifdef ASSERT
455453
Node* old = C->matcher()->find_old_node(node);
456454
if (old != NULL) {
457455
print_prop("old_node_idx", old->_idx);
458456
}
459-
#endif
460457
}
461458

462459
if (node->is_Proj()) {

src/hotspot/share/opto/matcher.cpp

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,11 @@ Matcher::Matcher()
7171
_end_inst_chain_rule(_END_INST_CHAIN_RULE),
7272
_must_clone(must_clone),
7373
_shared_nodes(C->comp_arena()),
74-
#ifdef ASSERT
74+
#ifndef PRODUCT
7575
_old2new_map(C->comp_arena()),
7676
_new2old_map(C->comp_arena()),
77-
#endif
77+
_reused(C->comp_arena()),
78+
#endif // !PRODUCT
7879
_allocation_started(false),
7980
_ruleName(ruleName),
8081
_register_save_policy(register_save_policy),
@@ -1098,16 +1099,12 @@ Node *Matcher::xform( Node *n, int max_stack ) {
10981099
if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Multi()) { // Projections?
10991100
// Convert to machine-dependent projection
11001101
m = n->in(0)->as_Multi()->match( n->as_Proj(), this );
1101-
#ifdef ASSERT
1102-
_new2old_map.map(m->_idx, n);
1103-
#endif
1102+
NOT_PRODUCT(record_new2old(m, n);)
11041103
if (m->in(0) != NULL) // m might be top
11051104
collect_null_checks(m, n);
11061105
} else { // Else just a regular 'ol guy
11071106
m = n->clone(); // So just clone into new-space
1108-
#ifdef ASSERT
1109-
_new2old_map.map(m->_idx, n);
1110-
#endif
1107+
NOT_PRODUCT(record_new2old(m, n);)
11111108
// Def-Use edges will be added incrementally as Uses
11121109
// of this node are matched.
11131110
assert(m->outcnt() == 0, "no Uses of this clone yet");
@@ -1165,9 +1162,7 @@ Node *Matcher::xform( Node *n, int max_stack ) {
11651162
// || op == Op_BoxLock // %%%% enable this and remove (+++) in chaitin.cpp
11661163
) {
11671164
m = m->clone();
1168-
#ifdef ASSERT
1169-
_new2old_map.map(m->_idx, n);
1170-
#endif
1165+
NOT_PRODUCT(record_new2old(m, n));
11711166
mstack.push(m, Post_Visit, n, i); // Don't need to visit
11721167
mstack.push(m->in(0), Visit, m, 0);
11731168
} else {
@@ -1499,10 +1494,8 @@ MachNode *Matcher::match_tree( const Node *n ) {
14991494
}
15001495
// Reduce input tree based upon the state labels to machine Nodes
15011496
MachNode *m = ReduceInst(s, s->rule(mincost), mem);
1502-
#ifdef ASSERT
1503-
_old2new_map.map(n->_idx, m);
1504-
_new2old_map.map(m->_idx, (Node*)n);
1505-
#endif
1497+
// New-to-old mapping is done in ReduceInst, to cover complex instructions.
1498+
NOT_PRODUCT(_old2new_map.map(n->_idx, m);)
15061499

15071500
// Add any Matcher-ignored edges
15081501
uint cnt = n->req();
@@ -1759,6 +1752,7 @@ MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) {
17591752
mach->_opnds[0] = s->MachOperGenerator(_reduceOp[rule]);
17601753
assert( mach->_opnds[0] != NULL, "Missing result operand" );
17611754
Node *leaf = s->_leaf;
1755+
NOT_PRODUCT(record_new2old(mach, leaf);)
17621756
// Check for instruction or instruction chain rule
17631757
if( rule >= _END_INST_CHAIN_RULE || rule < _BEGIN_INST_CHAIN_RULE ) {
17641758
assert(C->node_arena()->contains(s->_leaf) || !has_new_node(s->_leaf),
@@ -1827,9 +1821,7 @@ MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) {
18271821
for( uint i=0; i<mach->req(); i++ ) {
18281822
mach->set_req(i,NULL);
18291823
}
1830-
#ifdef ASSERT
1831-
_new2old_map.map(ex->_idx, s->_leaf);
1832-
#endif
1824+
NOT_PRODUCT(record_new2old(ex, s->_leaf);)
18331825
}
18341826

18351827
// PhaseChaitin::fixup_spills will sometimes generate spill code
@@ -2427,12 +2419,22 @@ void Matcher::find_shared_post_visit(Node* n, uint opcode) {
24272419
}
24282420
}
24292421

2430-
#ifdef ASSERT
2422+
#ifndef PRODUCT
2423+
void Matcher::record_new2old(Node* newn, Node* old) {
2424+
_new2old_map.map(newn->_idx, old);
2425+
if (!_reused.test_set(old->_igv_idx)) {
2426+
// Reuse the Ideal-level IGV identifier so that the node can be tracked
2427+
// across matching. If there are multiple machine nodes expanded from the
2428+
// same Ideal node, only one will reuse its IGV identifier.
2429+
newn->_igv_idx = old->_igv_idx;
2430+
}
2431+
}
2432+
24312433
// machine-independent root to machine-dependent root
24322434
void Matcher::dump_old2new_map() {
24332435
_old2new_map.dump();
24342436
}
2435-
#endif
2437+
#endif // !PRODUCT
24362438

24372439
//---------------------------collect_null_checks-------------------------------
24382440
// Find null checks in the ideal graph; write a machine-specific node for

src/hotspot/share/opto/matcher.hpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,11 @@ class Matcher : public PhaseTransform {
135135

136136
Node_Array _shared_nodes;
137137

138-
debug_only(Node_Array _old2new_map;) // Map roots of ideal-trees to machine-roots
139-
debug_only(Node_Array _new2old_map;) // Maps machine nodes back to ideal
138+
#ifndef PRODUCT
139+
Node_Array _old2new_map; // Map roots of ideal-trees to machine-roots
140+
Node_Array _new2old_map; // Maps machine nodes back to ideal
141+
VectorSet _reused; // Ideal IGV identifiers reused by machine nodes
142+
#endif // !PRODUCT
140143

141144
// Accessors for the inherited field PhaseTransform::_nodes:
142145
void grow_new_node_array(uint idx_limit) {
@@ -556,13 +559,16 @@ class Matcher : public PhaseTransform {
556559
// Does n lead to an uncommon trap that can cause deoptimization?
557560
static bool branches_to_uncommon_trap(const Node *n);
558561

559-
#ifdef ASSERT
562+
#ifndef PRODUCT
563+
// Record mach-to-Ideal mapping, reusing the Ideal IGV identifier if possible.
564+
void record_new2old(Node* newn, Node* old);
565+
560566
void dump_old2new_map(); // machine-independent to machine-dependent
561567

562568
Node* find_old_node(Node* new_node) {
563569
return _new2old_map[new_node->_idx];
564570
}
565-
#endif
571+
#endif // !PRODUCT
566572
};
567573

568574
#endif // SHARE_OPTO_MATCHER_HPP

src/hotspot/share/opto/node.hpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,11 @@ class Node {
322322
// preserved in _parse_idx.
323323
const node_idx_t _idx;
324324
DEBUG_ONLY(const node_idx_t _parse_idx;)
325-
// IGV node identifier. It is similar to Node::_debug_idx in that it is unique
326-
// across all compilation phases, but different in that it is initialized in
327-
// each compilation, for stability.
325+
// IGV node identifier. Two nodes, possibly in different compilation phases,
326+
// have the same IGV identifier if (and only if) they are the very same node
327+
// (same memory address) or one is "derived" from the other (by e.g.
328+
// renumbering or matching). This identifier makes it possible to follow the
329+
// entire lifetime of a node in IGV even if its C2 identifier (_idx) changes.
328330
NOT_PRODUCT(node_idx_t _igv_idx;)
329331

330332
// Get the (read-only) number of input edges

0 commit comments

Comments
 (0)