Skip to content
Permalink
Browse files
8255026: C2: Miscellaneous cleanups in Compile and PhaseIdealLoop code
Reviewed-by: thartmann, neliasso, redestad
  • Loading branch information
Vladimir Ivanov committed Oct 21, 2020
1 parent c107178 commit 27230fae24c67685b6567e79d9f5959176f536eb
@@ -119,38 +119,34 @@ class IntrinsicDescPair {
};
int Compile::intrinsic_insertion_index(ciMethod* m, bool is_virtual, bool& found) {
#ifdef ASSERT
for (int i = 1; i < _intrinsics->length(); i++) {
CallGenerator* cg1 = _intrinsics->at(i-1);
CallGenerator* cg2 = _intrinsics->at(i);
for (int i = 1; i < _intrinsics.length(); i++) {
CallGenerator* cg1 = _intrinsics.at(i-1);
CallGenerator* cg2 = _intrinsics.at(i);
assert(cg1->method() != cg2->method()
? cg1->method() < cg2->method()
: cg1->is_virtual() < cg2->is_virtual(),
"compiler intrinsics list must stay sorted");
}
#endif
IntrinsicDescPair pair(m, is_virtual);
return _intrinsics->find_sorted<IntrinsicDescPair*, IntrinsicDescPair::compare>(&pair, found);
return _intrinsics.find_sorted<IntrinsicDescPair*, IntrinsicDescPair::compare>(&pair, found);
}

void Compile::register_intrinsic(CallGenerator* cg) {
if (_intrinsics == NULL) {
_intrinsics = new (comp_arena())GrowableArray<CallGenerator*>(comp_arena(), 60, 0, NULL);
}
int len = _intrinsics->length();
bool found = false;
int index = intrinsic_insertion_index(cg->method(), cg->is_virtual(), found);
assert(!found, "registering twice");
_intrinsics->insert_before(index, cg);
_intrinsics.insert_before(index, cg);
assert(find_intrinsic(cg->method(), cg->is_virtual()) == cg, "registration worked");
}

CallGenerator* Compile::find_intrinsic(ciMethod* m, bool is_virtual) {
assert(m->is_loaded(), "don't try this on unloaded methods");
if (_intrinsics != NULL) {
if (_intrinsics.length() > 0) {
bool found = false;
int index = intrinsic_insertion_index(m, is_virtual, found);
if (found) {
return _intrinsics->at(index);
return _intrinsics.at(index);
}
}
// Lazily create intrinsics for intrinsic IDs well-known in the runtime.
@@ -168,9 +164,7 @@ CallGenerator* Compile::find_intrinsic(ciMethod* m, bool is_virtual) {
return NULL;
}

// Compile:: register_library_intrinsics and make_vm_intrinsic are defined
// in library_call.cpp.

// Compile::make_vm_intrinsic is defined in library_call.cpp.

#ifndef PRODUCT
// statistics gathering...
@@ -352,6 +346,15 @@ void Compile::remove_useless_late_inlines(GrowableArray<CallGenerator*>* inlines
inlines->trunc_to(inlines->length()-shift);
}

void Compile::remove_useless_nodes(GrowableArray<Node*>& node_list, Unique_Node_List& useful) {
for (int i = node_list.length() - 1; i >= 0; i--) {
Node* n = node_list.at(i);
if (!useful.member(n)) {
node_list.remove_if_existing(n);
}
}
}

// Disconnect all useless nodes by disconnecting those at the boundary.
void Compile::remove_useless_nodes(Unique_Node_List &useful) {
uint next = 0;
@@ -366,7 +369,7 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
int max = n->outcnt();
for (int j = 0; j < max; ++j) {
Node* child = n->raw_out(j);
if (! useful.member(child)) {
if (!useful.member(child)) {
assert(!child->is_top() || child != top(),
"If top is cached in Compile object it is in useful list");
// Only need to remove this out-edge to the useless node
@@ -379,34 +382,12 @@ void Compile::remove_useless_nodes(Unique_Node_List &useful) {
record_for_igvn(n->unique_out());
}
}
// Remove useless macro and predicate opaq nodes
for (int i = C->macro_count()-1; i >= 0; i--) {
Node* n = C->macro_node(i);
if (!useful.member(n)) {
remove_macro_node(n);
}
}
// Remove useless CastII nodes with range check dependency
for (int i = range_check_cast_count() - 1; i >= 0; i--) {
Node* cast = range_check_cast_node(i);
if (!useful.member(cast)) {
remove_range_check_cast(cast);
}
}
// Remove useless expensive nodes
for (int i = C->expensive_count()-1; i >= 0; i--) {
Node* n = C->expensive_node(i);
if (!useful.member(n)) {
remove_expensive_node(n);
}
}
// Remove useless Opaque4 nodes
for (int i = opaque4_count() - 1; i >= 0; i--) {
Node* opaq = opaque4_node(i);
if (!useful.member(opaq)) {
remove_opaque4_node(opaq);
}
}

remove_useless_nodes(_macro_nodes, useful); // remove useless macro and predicate opaq nodes
remove_useless_nodes(_expensive_nodes, useful); // remove useless expensive nodes
remove_useless_nodes(_range_check_casts, useful); // remove useless CastII nodes with range check dependency
remove_useless_nodes(_opaque4_nodes, useful); // remove useless Opaque4 nodes

BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
bs->eliminate_useless_gc_barriers(useful, this);
// clean up the late inline lists
@@ -533,6 +514,12 @@ Compile::Compile( ciEnv* ci_env, ciMethod* target, int osr_bci,
_directive(directive),
_log(ci_env->log()),
_failure_reason(NULL),
_intrinsics (comp_arena(), 0, 0, NULL),
_macro_nodes (comp_arena(), 8, 0, NULL),
_predicate_opaqs (comp_arena(), 8, 0, NULL),
_expensive_nodes (comp_arena(), 8, 0, NULL),
_range_check_casts (comp_arena(), 8, 0, NULL),
_opaque4_nodes (comp_arena(), 8, 0, NULL),
_congraph(NULL),
NOT_PRODUCT(_printer(NULL) COMMA)
_dead_node_list(comp_arena()),
@@ -1015,13 +1002,6 @@ void Compile::Init(int aliaslevel) {
// A NULL adr_type hits in the cache right away. Preload the right answer.
probe_alias_cache(NULL)->_index = AliasIdxTop;

_intrinsics = NULL;
_macro_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
_predicate_opaqs = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
_expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
_range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
_opaque4_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
register_library_intrinsics();
#ifdef ASSERT
_type_verify_symmetry = true;
_phase_optimize_finished = false;
@@ -1794,8 +1774,8 @@ void Compile::cleanup_loop_predicates(PhaseIterGVN &igvn) {

void Compile::add_range_check_cast(Node* n) {
assert(n->isa_CastII()->has_range_check(), "CastII should have range check dependency");
assert(!_range_check_casts->contains(n), "duplicate entry in range check casts");
_range_check_casts->append(n);
assert(!_range_check_casts.contains(n), "duplicate entry in range check casts");
_range_check_casts.append(n);
}

// Remove all range check dependent CastIINodes.
@@ -1810,8 +1790,8 @@ void Compile::remove_range_check_casts(PhaseIterGVN &igvn) {

void Compile::add_opaque4_node(Node* n) {
assert(n->Opcode() == Op_Opaque4, "Opaque4 only");
assert(!_opaque4_nodes->contains(n), "duplicate entry in Opaque4 list");
_opaque4_nodes->append(n);
assert(!_opaque4_nodes.contains(n), "duplicate entry in Opaque4 list");
_opaque4_nodes.append(n);
}

// Remove all Opaque4 nodes.
@@ -1988,9 +1968,9 @@ void Compile::inline_incrementally(PhaseIterGVN& igvn) {


bool Compile::optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode) {
if(_loop_opts_cnt > 0) {
if (_loop_opts_cnt > 0) {
debug_only( int cnt = 0; );
while(major_progress() && (_loop_opts_cnt > 0)) {
while (major_progress() && (_loop_opts_cnt > 0)) {
TracePhase tp("idealLoop", &timers[_t_idealLoop]);
assert( cnt++ < 40, "infinite cycle in loop optimization" );
PhaseIdealLoop::optimize(igvn, mode);
@@ -2273,6 +2253,7 @@ void Compile::Optimize() {
}

DEBUG_ONLY( _modified_nodes = NULL; )
assert(igvn._worklist.size() == 0, "not empty");
} // (End scope of igvn; run destructor if necessary for asserts.)

process_print_inlining();
@@ -3683,7 +3664,7 @@ bool Compile::final_graph_reshaping() {
// be freely moved to the least frequent code path by gcm.
assert(OptimizeExpensiveOps || expensive_count() == 0, "optimization off but list non empty?");
for (int i = 0; i < expensive_count(); i++) {
_expensive_nodes->at(i)->set_req(0, NULL);
_expensive_nodes.at(i)->set_req(0, NULL);
}

Final_Reshape_Counts frc;
@@ -4335,45 +4316,45 @@ int Compile::cmp_expensive_nodes(Node** n1p, Node** n2p) {

void Compile::sort_expensive_nodes() {
if (!expensive_nodes_sorted()) {
_expensive_nodes->sort(cmp_expensive_nodes);
_expensive_nodes.sort(cmp_expensive_nodes);
}
}

bool Compile::expensive_nodes_sorted() const {
for (int i = 1; i < _expensive_nodes->length(); i++) {
if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i-1)) < 0) {
for (int i = 1; i < _expensive_nodes.length(); i++) {
if (cmp_expensive_nodes(_expensive_nodes.adr_at(i), _expensive_nodes.adr_at(i-1)) < 0) {
return false;
}
}
return true;
}

bool Compile::should_optimize_expensive_nodes(PhaseIterGVN &igvn) {
if (_expensive_nodes->length() == 0) {
if (_expensive_nodes.length() == 0) {
return false;
}

assert(OptimizeExpensiveOps, "optimization off?");

// Take this opportunity to remove dead nodes from the list
int j = 0;
for (int i = 0; i < _expensive_nodes->length(); i++) {
Node* n = _expensive_nodes->at(i);
for (int i = 0; i < _expensive_nodes.length(); i++) {
Node* n = _expensive_nodes.at(i);
if (!n->is_unreachable(igvn)) {
assert(n->is_expensive(), "should be expensive");
_expensive_nodes->at_put(j, n);
_expensive_nodes.at_put(j, n);
j++;
}
}
_expensive_nodes->trunc_to(j);
_expensive_nodes.trunc_to(j);

// Then sort the list so that similar nodes are next to each other
// and check for at least two nodes of identical kind with same data
// inputs.
sort_expensive_nodes();

for (int i = 0; i < _expensive_nodes->length()-1; i++) {
if (cmp_expensive_nodes(_expensive_nodes->adr_at(i), _expensive_nodes->adr_at(i+1)) == 0) {
for (int i = 0; i < _expensive_nodes.length()-1; i++) {
if (cmp_expensive_nodes(_expensive_nodes.adr_at(i), _expensive_nodes.adr_at(i+1)) == 0) {
return true;
}
}
@@ -4382,7 +4363,7 @@ bool Compile::should_optimize_expensive_nodes(PhaseIterGVN &igvn) {
}

void Compile::cleanup_expensive_nodes(PhaseIterGVN &igvn) {
if (_expensive_nodes->length() == 0) {
if (_expensive_nodes.length() == 0) {
return;
}

@@ -4396,43 +4377,43 @@ void Compile::cleanup_expensive_nodes(PhaseIterGVN &igvn) {
int identical = 0;
int i = 0;
bool modified = false;
for (; i < _expensive_nodes->length()-1; i++) {
for (; i < _expensive_nodes.length()-1; i++) {
assert(j <= i, "can't write beyond current index");
if (_expensive_nodes->at(i)->Opcode() == _expensive_nodes->at(i+1)->Opcode()) {
if (_expensive_nodes.at(i)->Opcode() == _expensive_nodes.at(i+1)->Opcode()) {
identical++;
_expensive_nodes->at_put(j++, _expensive_nodes->at(i));
_expensive_nodes.at_put(j++, _expensive_nodes.at(i));
continue;
}
if (identical > 0) {
_expensive_nodes->at_put(j++, _expensive_nodes->at(i));
_expensive_nodes.at_put(j++, _expensive_nodes.at(i));
identical = 0;
} else {
Node* n = _expensive_nodes->at(i);
Node* n = _expensive_nodes.at(i);
igvn.replace_input_of(n, 0, NULL);
igvn.hash_insert(n);
modified = true;
}
}
if (identical > 0) {
_expensive_nodes->at_put(j++, _expensive_nodes->at(i));
} else if (_expensive_nodes->length() >= 1) {
Node* n = _expensive_nodes->at(i);
_expensive_nodes.at_put(j++, _expensive_nodes.at(i));
} else if (_expensive_nodes.length() >= 1) {
Node* n = _expensive_nodes.at(i);
igvn.replace_input_of(n, 0, NULL);
igvn.hash_insert(n);
modified = true;
}
_expensive_nodes->trunc_to(j);
_expensive_nodes.trunc_to(j);
if (modified) {
igvn.optimize();
}
}

void Compile::add_expensive_node(Node * n) {
assert(!_expensive_nodes->contains(n), "duplicate entry in expensive list");
assert(!_expensive_nodes.contains(n), "duplicate entry in expensive list");
assert(n->is_expensive(), "expensive nodes with non-null control here only");
assert(!n->is_CFG() && !n->is_Mem(), "no cfg or memory nodes here");
if (OptimizeExpensiveOps) {
_expensive_nodes->append(n);
_expensive_nodes.append(n);
} else {
// Clear control input and let IGVN optimize expensive nodes if
// OptimizeExpensiveOps is off.
@@ -4610,8 +4591,8 @@ void Compile::sort_macro_nodes() {
if (n->is_Allocate()) {
if (i != allocates) {
Node* tmp = macro_node(allocates);
_macro_nodes->at_put(allocates, n);
_macro_nodes->at_put(i, tmp);
_macro_nodes.at_put(allocates, n);
_macro_nodes.at_put(i, tmp);
}
allocates++;
}
Loading

1 comment on commit 27230fa

@bridgekeeper

This comment has been minimized.

Copy link

@bridgekeeper bridgekeeper bot commented on 27230fa Oct 21, 2020

Please sign in to comment.