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.
|
||||
*
|
||||
* 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
|
||||
// executed only when Precedent (== TypeFunc::Parms) edge is present.
|
||||
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->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.
|
||||
*
|
||||
* 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
|
||||
Node *n = in(idx);
|
||||
if (n != NULL) n->del_out((Node *)this);
|
||||
_in[idx] = in(--_cnt); // Compact the array
|
||||
_in[_cnt] = NULL; // NULL out emptied slot
|
||||
_in[idx] = in(--_cnt); // Compact the array
|
||||
// Avoid spec violation: Gap in prec edges.
|
||||
close_prec_gap_at(_cnt);
|
||||
Compile::current()->record_modified_node(this);
|
||||
}
|
||||
|
||||
@ -810,10 +811,11 @@ void Node::del_req_ordered( uint idx ) {
|
||||
// First remove corresponding def-use edge
|
||||
Node *n = in(idx);
|
||||
if (n != NULL) n->del_out((Node *)this);
|
||||
if (idx < _cnt - 1) { // Not last edge ?
|
||||
Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*)));
|
||||
if (idx < --_cnt) { // Not last edge ?
|
||||
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);
|
||||
}
|
||||
|
||||
@ -845,10 +847,12 @@ int Node::replace_edge(Node* old, Node* neww) {
|
||||
uint nrep = 0;
|
||||
for (uint i = 0; i < len(); i++) {
|
||||
if (in(i) == old) {
|
||||
if (i < req())
|
||||
if (i < req()) {
|
||||
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);
|
||||
}
|
||||
nrep++;
|
||||
}
|
||||
}
|
||||
@ -982,24 +986,27 @@ void Node::add_prec( Node *n ) {
|
||||
|
||||
// Find a precedence edge to move
|
||||
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
|
||||
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----------------------------------------
|
||||
// Remove a precedence input. Precedence inputs are unordered, with
|
||||
// duplicates removed and NULLs packed down at the end.
|
||||
void Node::rm_prec( uint j ) {
|
||||
|
||||
// Find end of precedence list to pack NULLs
|
||||
uint i;
|
||||
for( i=j; i<_max; i++ )
|
||||
if( !_in[i] ) // Find the NULL at end of prec edge list
|
||||
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
|
||||
assert(j < _max, "oob: i=%d, _max=%d", j, _max);
|
||||
assert(j >= _cnt, "not a precedence edge");
|
||||
if (_in[j] == NULL) return; // Avoid spec violation: Gap in prec edges.
|
||||
_in[j]->del_out((Node *)this);
|
||||
close_prec_gap_at(j);
|
||||
}
|
||||
|
||||
//------------------------------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.
|
||||
*
|
||||
* 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:
|
||||
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_edges_in_range(Node* old, Node* neww, int start, int end);
|
||||
// NULL out all inputs to eliminate incoming Def-Use edges.
|
||||
@ -476,6 +486,19 @@ private:
|
||||
debug_only(_last_del = n; ++_del_tick);
|
||||
#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:
|
||||
// Globally replace this node by a given new node, updating all uses.
|
||||
@ -492,13 +515,23 @@ public:
|
||||
// Add or remove precedence edges
|
||||
void add_prec( Node *n );
|
||||
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 ) {
|
||||
assert( is_not_dead(n), "can not use dead node");
|
||||
assert( i >= _cnt, "not a precedence edge");
|
||||
assert(i < _max, "oob: i=%d, _max=%d", i, _max);
|
||||
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);
|
||||
_in[i] = n;
|
||||
if (n != NULL) n->add_out((Node *)this);
|
||||
}
|
||||
|
||||
// Set this node's index, used by cisc_version to replace current node
|
||||
void set_idx(uint new_idx) {
|
||||
const node_idx_t* ref = &_idx;
|
||||
|
Loading…
x
Reference in New Issue
Block a user