< prev index next >
src/hotspot/share/opto/loopUnswitch.cpp
Print this page
@@ -128,11 +128,15 @@
loop->is_invariant(n->in(1)) &&
!loop->is_loop_exit(n)) {
flattened_checks.push(n);
}
}
+ if (flattened_checks.size() > 1) {
unswitch_iff = NULL;
+ } else {
+ flattened_checks.clear();
+ }
}
return unswitch_iff;
}
@@ -194,11 +198,13 @@
// Increment unswitch count
LoopNode* head_clone = old_new[head->_idx]->as_Loop();
int nct = head->unswitch_count() + 1;
head->set_unswitch_count(nct);
head_clone->set_unswitch_count(nct);
- head_clone->mark_flattened_arrays();
+ if (flattened_checks.size() > 0) {
+ head->mark_flattened_arrays();
+ }
// Add test to new "if" outside of loop
IfNode* invar_iff = proj_true->in(0)->as_If();
Node* invar_iff_c = invar_iff->in(0);
invar_iff->_prob = unswitch_iff->_prob;
@@ -218,16 +224,18 @@
register_new_node(cmp, invar_iff->in(0));
bol->set_req(1, cmp);
Node* in1 = NULL;
for (uint i = 0; i < flattened_checks.size(); i++) {
Node* v = flattened_checks.at(i)->in(1)->in(1)->in(1);
- v = new AndINode(v, _igvn.intcon(Klass::_lh_array_tag_vt_value));
- register_new_node(v, invar_iff->in(0));
if (in1 == NULL) {
in1 = v;
} else {
+ if (cmp->Opcode() == Op_CmpL) {
+ in1 = new OrLNode(in1, v);
+ } else {
in1 = new OrINode(in1, v);
+ }
register_new_node(in1, invar_iff->in(0));
}
}
cmp->set_req(1, in1);
invar_iff->set_req(1, bol);
@@ -241,10 +249,34 @@
// Hoist invariant casts out of each loop to the appropriate
// control projection.
Node_List worklist;
+ if (flattened_checks.size() > 0) {
+ for (uint i = 0; i < flattened_checks.size(); i++) {
+ IfNode* iff = flattened_checks.at(i)->as_If();
+ ProjNode* proj= iff->proj_out(0)->as_Proj();
+ // Copy to a worklist for easier manipulation
+ for (DUIterator_Fast jmax, j = proj->fast_outs(jmax); j < jmax; j++) {
+ Node* use = proj->fast_out(j);
+ if (use->Opcode() == Op_CheckCastPP && loop->is_invariant(use->in(1))) {
+ worklist.push(use);
+ }
+ }
+ ProjNode* invar_proj = invar_iff->proj_out(proj->_con)->as_Proj();
+ while (worklist.size() > 0) {
+ Node* use = worklist.pop();
+ Node* nuse = use->clone();
+ nuse->set_req(0, invar_proj);
+ _igvn.replace_input_of(use, 1, nuse);
+ register_new_node(nuse, invar_proj);
+ // Same for the clone
+ Node* use_clone = old_new[use->_idx];
+ _igvn.replace_input_of(use_clone, 1, nuse);
+ }
+ }
+ } else {
for (DUIterator_Fast imax, i = unswitch_iff->fast_outs(imax); i < imax; i++) {
ProjNode* proj= unswitch_iff->fast_out(i)->as_Proj();
// Copy to a worklist for easier manipulation
for (DUIterator_Fast jmax, j = proj->fast_outs(jmax); j < jmax; j++) {
Node* use = proj->fast_out(j);
@@ -262,17 +294,18 @@
// Same for the clone
Node* use_clone = old_new[use->_idx];
_igvn.replace_input_of(use_clone, 1, nuse);
}
}
+ }
IfNode* unswitch_iff_clone = old_new[unswitch_iff->_idx]->as_If();
if (flattened_checks.size() > 0) {
for (uint i = 0; i < flattened_checks.size(); i++) {
IfNode* iff = flattened_checks.at(i)->as_If();
_igvn.rehash_node_delayed(iff);
- short_circuit_if(iff, proj_true);
+ short_circuit_if(old_new[iff->_idx]->as_If(), proj_false);
}
} else {
// Hardwire the control paths in the loops into if(true) and if(false)
_igvn.rehash_node_delayed(unswitch_iff);
short_circuit_if(unswitch_iff, proj_true);
< prev index next >