8146612: C2: Precedence edges specification violated
Reviewed-by: kvn
This commit is contained in:
parent
307d39879b
commit
ad3414f985
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -949,6 +949,13 @@ bool PhaseCFG::schedule_local(Block* block, GrowableArray<int>& ready_cnt, Vecto
|
|||||||
// and the edge will be lost. This is why this code should be
|
// and the edge will be lost. This is why this code should be
|
||||||
// executed only when Precedent (== TypeFunc::Parms) edge is present.
|
// executed only when Precedent (== TypeFunc::Parms) edge is present.
|
||||||
Node *x = n->in(TypeFunc::Parms);
|
Node *x = n->in(TypeFunc::Parms);
|
||||||
|
if (x != NULL && get_block_for_node(x) == block && n->find_prec_edge(x) != -1) {
|
||||||
|
// Old edge to node within same block will get removed, but no precedence
|
||||||
|
// edge will get added because it already exists. Update ready count.
|
||||||
|
int cnt = ready_cnt.at(n->_idx);
|
||||||
|
assert(cnt > 1, "MemBar node %d must not get ready here", n->_idx);
|
||||||
|
ready_cnt.at_put(n->_idx, cnt-1);
|
||||||
|
}
|
||||||
n->del_req(TypeFunc::Parms);
|
n->del_req(TypeFunc::Parms);
|
||||||
n->add_prec(x);
|
n->add_prec(x);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -796,8 +796,9 @@ void Node::del_req( uint idx ) {
|
|||||||
// First remove corresponding def-use edge
|
// First remove corresponding def-use edge
|
||||||
Node *n = in(idx);
|
Node *n = in(idx);
|
||||||
if (n != NULL) n->del_out((Node *)this);
|
if (n != NULL) n->del_out((Node *)this);
|
||||||
_in[idx] = in(--_cnt); // Compact the array
|
_in[idx] = in(--_cnt); // Compact the array
|
||||||
_in[_cnt] = NULL; // NULL out emptied slot
|
// Avoid spec violation: Gap in prec edges.
|
||||||
|
close_prec_gap_at(_cnt);
|
||||||
Compile::current()->record_modified_node(this);
|
Compile::current()->record_modified_node(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -810,10 +811,11 @@ void Node::del_req_ordered( uint idx ) {
|
|||||||
// First remove corresponding def-use edge
|
// First remove corresponding def-use edge
|
||||||
Node *n = in(idx);
|
Node *n = in(idx);
|
||||||
if (n != NULL) n->del_out((Node *)this);
|
if (n != NULL) n->del_out((Node *)this);
|
||||||
if (idx < _cnt - 1) { // Not last edge ?
|
if (idx < --_cnt) { // Not last edge ?
|
||||||
Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*)));
|
Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx)*sizeof(Node*)));
|
||||||
}
|
}
|
||||||
_in[--_cnt] = NULL; // NULL out emptied slot
|
// Avoid spec violation: Gap in prec edges.
|
||||||
|
close_prec_gap_at(_cnt);
|
||||||
Compile::current()->record_modified_node(this);
|
Compile::current()->record_modified_node(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -845,10 +847,12 @@ int Node::replace_edge(Node* old, Node* neww) {
|
|||||||
uint nrep = 0;
|
uint nrep = 0;
|
||||||
for (uint i = 0; i < len(); i++) {
|
for (uint i = 0; i < len(); i++) {
|
||||||
if (in(i) == old) {
|
if (in(i) == old) {
|
||||||
if (i < req())
|
if (i < req()) {
|
||||||
set_req(i, neww);
|
set_req(i, neww);
|
||||||
else
|
} else {
|
||||||
|
assert(find_prec_edge(neww) == -1, "spec violation: duplicated prec edge (node %d -> %d)", _idx, neww->_idx);
|
||||||
set_prec(i, neww);
|
set_prec(i, neww);
|
||||||
|
}
|
||||||
nrep++;
|
nrep++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -982,24 +986,27 @@ void Node::add_prec( Node *n ) {
|
|||||||
|
|
||||||
// Find a precedence edge to move
|
// Find a precedence edge to move
|
||||||
uint i = _cnt;
|
uint i = _cnt;
|
||||||
while( in(i) != NULL ) i++;
|
while( in(i) != NULL ) {
|
||||||
|
if (in(i) == n) return; // Avoid spec violation: duplicated prec edge.
|
||||||
|
i++;
|
||||||
|
}
|
||||||
_in[i] = n; // Stuff prec edge over NULL
|
_in[i] = n; // Stuff prec edge over NULL
|
||||||
if ( n != NULL) n->add_out((Node *)this); // Add mirror edge
|
if ( n != NULL) n->add_out((Node *)this); // Add mirror edge
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
while ((++i)<_max) { assert(_in[i] == NULL, "spec violation: Gap in prec edges (node %d)", _idx); }
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------rm_prec----------------------------------------
|
//------------------------------rm_prec----------------------------------------
|
||||||
// Remove a precedence input. Precedence inputs are unordered, with
|
// Remove a precedence input. Precedence inputs are unordered, with
|
||||||
// duplicates removed and NULLs packed down at the end.
|
// duplicates removed and NULLs packed down at the end.
|
||||||
void Node::rm_prec( uint j ) {
|
void Node::rm_prec( uint j ) {
|
||||||
|
assert(j < _max, "oob: i=%d, _max=%d", j, _max);
|
||||||
// Find end of precedence list to pack NULLs
|
assert(j >= _cnt, "not a precedence edge");
|
||||||
uint i;
|
if (_in[j] == NULL) return; // Avoid spec violation: Gap in prec edges.
|
||||||
for( i=j; i<_max; i++ )
|
_in[j]->del_out((Node *)this);
|
||||||
if( !_in[i] ) // Find the NULL at end of prec edge list
|
close_prec_gap_at(j);
|
||||||
break;
|
|
||||||
if (_in[j] != NULL) _in[j]->del_out((Node *)this);
|
|
||||||
_in[j] = _in[--i]; // Move last element over removed guy
|
|
||||||
_in[i] = NULL; // NULL out last element
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------size_of----------------------------------------
|
//------------------------------size_of----------------------------------------
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -423,6 +423,16 @@ protected:
|
|||||||
}
|
}
|
||||||
// Find first occurrence of n among my edges:
|
// Find first occurrence of n among my edges:
|
||||||
int find_edge(Node* n);
|
int find_edge(Node* n);
|
||||||
|
int find_prec_edge(Node* n) {
|
||||||
|
for (uint i = req(); i < len(); i++) {
|
||||||
|
if (_in[i] == n) return i;
|
||||||
|
if (_in[i] == NULL) {
|
||||||
|
DEBUG_ONLY( while ((++i) < len()) assert(_in[i] == NULL, "Gap in prec edges!"); )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
int replace_edge(Node* old, Node* neww);
|
int replace_edge(Node* old, Node* neww);
|
||||||
int replace_edges_in_range(Node* old, Node* neww, int start, int end);
|
int replace_edges_in_range(Node* old, Node* neww, int start, int end);
|
||||||
// NULL out all inputs to eliminate incoming Def-Use edges.
|
// NULL out all inputs to eliminate incoming Def-Use edges.
|
||||||
@ -476,6 +486,19 @@ private:
|
|||||||
debug_only(_last_del = n; ++_del_tick);
|
debug_only(_last_del = n; ++_del_tick);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
// Close gap after removing edge.
|
||||||
|
void close_prec_gap_at(uint gap) {
|
||||||
|
assert(_cnt <= gap && gap < _max, "no valid prec edge");
|
||||||
|
uint i = gap;
|
||||||
|
Node *last = NULL;
|
||||||
|
for (; i < _max-1; ++i) {
|
||||||
|
Node *next = _in[i+1];
|
||||||
|
if (next == NULL) break;
|
||||||
|
last = next;
|
||||||
|
}
|
||||||
|
_in[gap] = last; // Move last slot to empty one.
|
||||||
|
_in[i] = NULL; // NULL out last slot.
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Globally replace this node by a given new node, updating all uses.
|
// Globally replace this node by a given new node, updating all uses.
|
||||||
@ -492,13 +515,23 @@ public:
|
|||||||
// Add or remove precedence edges
|
// Add or remove precedence edges
|
||||||
void add_prec( Node *n );
|
void add_prec( Node *n );
|
||||||
void rm_prec( uint i );
|
void rm_prec( uint i );
|
||||||
|
|
||||||
|
// Note: prec(i) will not necessarily point to n if edge already exists.
|
||||||
void set_prec( uint i, Node *n ) {
|
void set_prec( uint i, Node *n ) {
|
||||||
assert( is_not_dead(n), "can not use dead node");
|
assert(i < _max, "oob: i=%d, _max=%d", i, _max);
|
||||||
assert( i >= _cnt, "not a precedence edge");
|
assert(is_not_dead(n), "can not use dead node");
|
||||||
|
assert(i >= _cnt, "not a precedence edge");
|
||||||
|
// Avoid spec violation: duplicated prec edge.
|
||||||
|
if (_in[i] == n) return;
|
||||||
|
if (n == NULL || find_prec_edge(n) != -1) {
|
||||||
|
rm_prec(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (_in[i] != NULL) _in[i]->del_out((Node *)this);
|
if (_in[i] != NULL) _in[i]->del_out((Node *)this);
|
||||||
_in[i] = n;
|
_in[i] = n;
|
||||||
if (n != NULL) n->add_out((Node *)this);
|
if (n != NULL) n->add_out((Node *)this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set this node's index, used by cisc_version to replace current node
|
// Set this node's index, used by cisc_version to replace current node
|
||||||
void set_idx(uint new_idx) {
|
void set_idx(uint new_idx) {
|
||||||
const node_idx_t* ref = &_idx;
|
const node_idx_t* ref = &_idx;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user