@@ -423,7 +423,7 @@ PhaseRemoveUseless::PhaseRemoveUseless(PhaseGVN* gvn, Unique_Node_List* worklist
423
423
worklist->remove_useless_nodes (_useful.member_set ());
424
424
425
425
// Disconnect 'useless' nodes that are adjacent to useful nodes
426
- C->remove_useless_nodes (_useful);
426
+ C->disconnect_useless_nodes (_useful, worklist );
427
427
}
428
428
429
429
// =============================================================================
@@ -1764,6 +1764,9 @@ void PhaseCCP::analyze() {
1764
1764
Unique_Node_List worklist;
1765
1765
worklist.push (C->root ());
1766
1766
1767
+ assert (_root_and_safepoints.size () == 0 , " must be empty (unused)" );
1768
+ _root_and_safepoints.push (C->root ());
1769
+
1767
1770
// Pull from worklist; compute new value; push changes out.
1768
1771
// This loop is the meat of CCP.
1769
1772
while ( worklist.size () ) {
@@ -1774,8 +1777,9 @@ void PhaseCCP::analyze() {
1774
1777
n = worklist.pop ();
1775
1778
}
1776
1779
if (n->is_SafePoint ()) {
1777
- // Keep track of SafePoint nodes for PhaseCCP::transform()
1778
- _safepoints.push (n);
1780
+ // Make sure safepoints are processed by PhaseCCP::transform even if they are
1781
+ // not reachable from the bottom. Otherwise, infinite loops would be removed.
1782
+ _root_and_safepoints.push (n);
1779
1783
}
1780
1784
const Type *t = n->Value (this );
1781
1785
if (t != type (n)) {
@@ -1904,32 +1908,34 @@ Node *PhaseCCP::transform( Node *n ) {
1904
1908
Node *new_node = _nodes[n->_idx ]; // Check for transformed node
1905
1909
if ( new_node != NULL )
1906
1910
return new_node; // Been there, done that, return old answer
1907
- new_node = transform_once (n); // Check for constant
1908
- _nodes.map ( n->_idx , new_node ); // Flag as having been cloned
1909
1911
1910
- // Allocate stack of size _nodes.Size()/2 to avoid frequent realloc
1911
- GrowableArray <Node *> trstack (C-> live_nodes () >> 1 );
1912
+ assert (n-> is_Root (), " traversal must start at root " );
1913
+ assert (_root_and_safepoints. member (n), " root (n) must be in list " );
1912
1914
1913
- trstack.push (new_node); // Process children of cloned node
1915
+ // Allocate stack of size _nodes.Size()/2 to avoid frequent realloc
1916
+ GrowableArray <Node *> transform_stack (C->live_nodes () >> 1 );
1917
+ Unique_Node_List useful; // track all visited nodes, so that we can remove the complement
1914
1918
1919
+ // Initialize the traversal.
1915
1920
// This CCP pass may prove that no exit test for a loop ever succeeds (i.e. the loop is infinite). In that case,
1916
1921
// the logic below doesn't follow any path from Root to the loop body: there's at least one such path but it's proven
1917
1922
// never taken (its type is TOP). As a consequence the node on the exit path that's input to Root (let's call it n) is
1918
1923
// replaced by the top node and the inputs of that node n are not enqueued for further processing. If CCP only works
1919
1924
// through the graph from Root, this causes the loop body to never be processed here even when it's not dead (that
1920
1925
// is reachable from Root following its uses). To prevent that issue, transform() starts walking the graph from Root
1921
1926
// and all safepoints.
1922
- for (uint i = 0 ; i < _safepoints .size (); ++i) {
1923
- Node* nn = _safepoints .at (i);
1927
+ for (uint i = 0 ; i < _root_and_safepoints .size (); ++i) {
1928
+ Node* nn = _root_and_safepoints .at (i);
1924
1929
Node* new_node = _nodes[nn->_idx ];
1925
1930
assert (new_node == NULL , " " );
1926
- new_node = transform_once (nn);
1927
- _nodes.map (nn->_idx , new_node);
1928
- trstack.push (new_node);
1931
+ new_node = transform_once (nn); // Check for constant
1932
+ _nodes.map (nn->_idx , new_node); // Flag as having been cloned
1933
+ transform_stack.push (new_node); // Process children of cloned node
1934
+ useful.push (new_node);
1929
1935
}
1930
1936
1931
- while ( trstack .is_nonempty () ) {
1932
- Node * clone = trstack .pop ();
1937
+ while (transform_stack .is_nonempty ()) {
1938
+ Node* clone = transform_stack .pop ();
1933
1939
uint cnt = clone->req ();
1934
1940
for ( uint i = 0 ; i < cnt; i++ ) { // For all inputs do
1935
1941
Node *input = clone->in (i);
@@ -1938,13 +1944,33 @@ Node *PhaseCCP::transform( Node *n ) {
1938
1944
if ( new_input == NULL ) {
1939
1945
new_input = transform_once (input); // Check for constant
1940
1946
_nodes.map ( input->_idx , new_input );// Flag as having been cloned
1941
- trstack.push (new_input);
1947
+ transform_stack.push (new_input); // Process children of cloned node
1948
+ useful.push (new_input);
1942
1949
}
1943
1950
assert ( new_input == clone->in (i), " insanity check" );
1944
1951
}
1945
1952
}
1946
1953
}
1947
- return new_node;
1954
+
1955
+ // The above transformation might lead to subgraphs becoming unreachable from the
1956
+ // bottom while still being reachable from the top. As a result, nodes in that
1957
+ // subgraph are not transformed and their bottom types are not updated, leading to
1958
+ // an inconsistency between bottom_type() and type(). In rare cases, LoadNodes in
1959
+ // such a subgraph, might be re-enqueued for IGVN indefinitely by MemNode::Ideal_common
1960
+ // because their address type is inconsistent. Therefore, we aggressively remove
1961
+ // all useless nodes here even before PhaseIdealLoop::build_loop_late gets a chance
1962
+ // to remove them anyway.
1963
+ if (C->cached_top_node ()) {
1964
+ useful.push (C->cached_top_node ());
1965
+ }
1966
+ C->update_dead_node_list (useful);
1967
+ remove_useless_nodes (useful.member_set ());
1968
+ _worklist.remove_useless_nodes (useful.member_set ());
1969
+ C->disconnect_useless_nodes (useful, &_worklist);
1970
+
1971
+ Node* new_root = _nodes[n->_idx ];
1972
+ assert (new_root->is_Root (), " transformed root node must be a root node" );
1973
+ return new_root;
1948
1974
}
1949
1975
1950
1976
1 commit comments
openjdk-notifier[bot] commentedon Nov 23, 2022
Review
Issues