Skip to content
Permalink
Browse files
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
  • Loading branch information
Roberto Castañeda Lozano committed Apr 28, 2021
1 parent 164454f commit e879f8c6c874cc7039d344f19430cce7cfb138ea
Showing with 37 additions and 30 deletions.
  1. +0 −3 src/hotspot/share/opto/idealGraphPrinter.cpp
  2. +22 −20 src/hotspot/share/opto/matcher.cpp
  3. +10 −4 src/hotspot/share/opto/matcher.hpp
  4. +5 −3 src/hotspot/share/opto/node.hpp
@@ -450,13 +450,10 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
} else {
print_prop("is_dontcare", "false");
}

#ifdef ASSERT
Node* old = C->matcher()->find_old_node(node);
if (old != NULL) {
print_prop("old_node_idx", old->_idx);
}
#endif
}

if (node->is_Proj()) {
@@ -71,10 +71,11 @@ Matcher::Matcher()
_end_inst_chain_rule(_END_INST_CHAIN_RULE),
_must_clone(must_clone),
_shared_nodes(C->comp_arena()),
#ifdef ASSERT
#ifndef PRODUCT
_old2new_map(C->comp_arena()),
_new2old_map(C->comp_arena()),
#endif
_reused(C->comp_arena()),
#endif // !PRODUCT
_allocation_started(false),
_ruleName(ruleName),
_register_save_policy(register_save_policy),
@@ -1098,16 +1099,12 @@ Node *Matcher::xform( Node *n, int max_stack ) {
if (n->is_Proj() && n->in(0) != NULL && n->in(0)->is_Multi()) { // Projections?
// Convert to machine-dependent projection
m = n->in(0)->as_Multi()->match( n->as_Proj(), this );
#ifdef ASSERT
_new2old_map.map(m->_idx, n);
#endif
NOT_PRODUCT(record_new2old(m, n);)
if (m->in(0) != NULL) // m might be top
collect_null_checks(m, n);
} else { // Else just a regular 'ol guy
m = n->clone(); // So just clone into new-space
#ifdef ASSERT
_new2old_map.map(m->_idx, n);
#endif
NOT_PRODUCT(record_new2old(m, n);)
// Def-Use edges will be added incrementally as Uses
// of this node are matched.
assert(m->outcnt() == 0, "no Uses of this clone yet");
@@ -1165,9 +1162,7 @@ Node *Matcher::xform( Node *n, int max_stack ) {
// || op == Op_BoxLock // %%%% enable this and remove (+++) in chaitin.cpp
) {
m = m->clone();
#ifdef ASSERT
_new2old_map.map(m->_idx, n);
#endif
NOT_PRODUCT(record_new2old(m, n));
mstack.push(m, Post_Visit, n, i); // Don't need to visit
mstack.push(m->in(0), Visit, m, 0);
} else {
@@ -1499,10 +1494,8 @@ MachNode *Matcher::match_tree( const Node *n ) {
}
// Reduce input tree based upon the state labels to machine Nodes
MachNode *m = ReduceInst(s, s->rule(mincost), mem);
#ifdef ASSERT
_old2new_map.map(n->_idx, m);
_new2old_map.map(m->_idx, (Node*)n);
#endif
// New-to-old mapping is done in ReduceInst, to cover complex instructions.
NOT_PRODUCT(_old2new_map.map(n->_idx, m);)

// Add any Matcher-ignored edges
uint cnt = n->req();
@@ -1759,6 +1752,7 @@ MachNode *Matcher::ReduceInst( State *s, int rule, Node *&mem ) {
mach->_opnds[0] = s->MachOperGenerator(_reduceOp[rule]);
assert( mach->_opnds[0] != NULL, "Missing result operand" );
Node *leaf = s->_leaf;
NOT_PRODUCT(record_new2old(mach, leaf);)
// Check for instruction or instruction chain rule
if( rule >= _END_INST_CHAIN_RULE || rule < _BEGIN_INST_CHAIN_RULE ) {
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 ) {
for( uint i=0; i<mach->req(); i++ ) {
mach->set_req(i,NULL);
}
#ifdef ASSERT
_new2old_map.map(ex->_idx, s->_leaf);
#endif
NOT_PRODUCT(record_new2old(ex, s->_leaf);)
}

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

#ifdef ASSERT
#ifndef PRODUCT
void Matcher::record_new2old(Node* newn, Node* old) {
_new2old_map.map(newn->_idx, old);
if (!_reused.test_set(old->_igv_idx)) {
// Reuse the Ideal-level IGV identifier so that the node can be tracked
// across matching. If there are multiple machine nodes expanded from the
// same Ideal node, only one will reuse its IGV identifier.
newn->_igv_idx = old->_igv_idx;
}
}

// machine-independent root to machine-dependent root
void Matcher::dump_old2new_map() {
_old2new_map.dump();
}
#endif
#endif // !PRODUCT

//---------------------------collect_null_checks-------------------------------
// Find null checks in the ideal graph; write a machine-specific node for
@@ -135,8 +135,11 @@ class Matcher : public PhaseTransform {

Node_Array _shared_nodes;

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

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

#ifdef ASSERT
#ifndef PRODUCT
// Record mach-to-Ideal mapping, reusing the Ideal IGV identifier if possible.
void record_new2old(Node* newn, Node* old);

void dump_old2new_map(); // machine-independent to machine-dependent

Node* find_old_node(Node* new_node) {
return _new2old_map[new_node->_idx];
}
#endif
#endif // !PRODUCT
};

#endif // SHARE_OPTO_MATCHER_HPP
@@ -322,9 +322,11 @@ class Node {
// preserved in _parse_idx.
const node_idx_t _idx;
DEBUG_ONLY(const node_idx_t _parse_idx;)
// IGV node identifier. It is similar to Node::_debug_idx in that it is unique
// across all compilation phases, but different in that it is initialized in
// each compilation, for stability.
// IGV node identifier. Two nodes, possibly in different compilation phases,
// have the same IGV identifier if (and only if) they are the very same node
// (same memory address) or one is "derived" from the other (by e.g.
// renumbering or matching). This identifier makes it possible to follow the
// entire lifetime of a node in IGV even if its C2 identifier (_idx) changes.
NOT_PRODUCT(node_idx_t _igv_idx;)

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

1 comment on commit e879f8c

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on e879f8c Apr 28, 2021

Please sign in to comment.