mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-21 19:08:31 +00:00
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
This commit is contained in:
parent
164454feeb
commit
e879f8c6c8
@ -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 @@ private:
|
||||
|
||||
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 @@ public:
|
||||
// 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 @@ protected:
|
||||
// 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user