src/share/vm/opto/ifnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/ifnode.cpp Thu Feb 19 16:21:11 2015
--- new/src/share/vm/opto/ifnode.cpp Thu Feb 19 16:21:11 2015
*** 28,37 ****
--- 28,38 ----
#include "opto/cfgnode.hpp"
#include "opto/connode.hpp"
#include "opto/loopnode.hpp"
#include "opto/phaseX.hpp"
#include "opto/runtime.hpp"
+ #include "opto/rootnode.hpp"
#include "opto/subnode.hpp"
// Portions of code courtesy of Clifford Click
// Optimization - Graph Style
*** 447,512 ****
--- 448,510 ----
// Must return either the original node (now dead) or a new node
// (Do not return a top here, since that would break the uniqueness of top.)
return new ConINode(TypeInt::ZERO);
}
//------------------------------is_range_check---------------------------------
// Return 0 if not a range check. Return 1 if a range check and set index and
// offset. Return 2 if we had to negate the test. Index is NULL if the check
// is versus a constant.
int IfNode::is_range_check(Node* &range, Node* &index, jint &offset) {
+ // if this IfNode follows a range check pattern return the projection
+ // for the failed path
+ ProjNode* IfNode::range_check_trap_proj(int& flip_test, Node*& l, Node*& r) {
Node* b = in(1);
! if (b == NULL || !b->is_Bool()) return 0;
! if (b == NULL || !b->is_Bool()) return NULL;
BoolNode* bn = b->as_Bool();
Node* cmp = bn->in(1);
! if (cmp == NULL) return 0;
! if (cmp->Opcode() != Op_CmpU) return 0;
! if (cmp == NULL) return NULL;
! if (cmp->Opcode() != Op_CmpU) return NULL;
- Node* l = cmp->in(1);
- Node* r = cmp->in(2);
- int flip_test = 1;
if (bn->_test._test == BoolTest::le) {
l = cmp->in(2);
r = cmp->in(1);
flip_test = 2;
} else if (bn->_test._test != BoolTest::lt) {
! return 0;
! return NULL;
}
! if (l->is_top()) return 0; // Top input means dead test
! if (r->Opcode() != Op_LoadRange) return 0;
! if (l->is_top()) return NULL; // Top input means dead test
! if (r->Opcode() != Op_LoadRange) return NULL;
// We have recognized one of these forms:
// Flip 1: If (Bool[<] CmpU(l, LoadRange)) ...
// Flip 2: If (Bool[<=] CmpU(LoadRange, l)) ...
+ ProjNode* iftrap = proj_out(flip_test == 2 ? true : false);
+ return iftrap;
+ }
+
+
+ //------------------------------is_range_check---------------------------------
+ // Return 0 if not a range check. Return 1 if a range check and set index and
+ // offset. Return 2 if we had to negate the test. Index is NULL if the check
+ // is versus a constant.
+ int IfNode::is_range_check(Node* &range, Node* &index, jint &offset) {
+ int flip_test = 0;
+ Node* l = NULL;
+ Node* r = NULL;
+ ProjNode* iftrap = range_check_trap_proj(flip_test, l, r);
+
+ if (iftrap == NULL) {
+ return 0;
+ }
+
// Make sure it's a real range check by requiring an uncommon trap
// along the OOB path. Otherwise, it's possible that the user wrote
// something which optimized to look like a range check but behaves
// in some other way.
Node* iftrap = proj_out(flip_test == 2 ? true : false);
! bool found_trap = false;
if (iftrap != NULL) {
Node* u = iftrap->unique_ctrl_out();
if (u != NULL) {
// It could be a merge point (Region) for uncommon trap.
if (u->is_Region()) {
Node* c = u->unique_ctrl_out();
if (c != NULL) {
iftrap = u;
u = c;
}
}
if (u->in(0) == iftrap && u->is_CallStaticJava()) {
int req = u->as_CallStaticJava()->uncommon_trap_request();
if (Deoptimization::trap_request_reason(req) ==
Deoptimization::Reason_range_check) {
found_trap = true;
}
}
}
+ if (iftrap->is_uncommon_trap_proj(Deoptimization::Reason_range_check) == NULL) {
! return 0;
}
if (!found_trap) return 0; // sorry, no cigar
// Look for index+offset form
Node* ind = l;
jint off = 0;
if (l->is_top()) {
*** 662,676 ****
--- 660,675 ----
}
//------------------------------fold_compares----------------------------
// See if a pair of CmpIs can be converted into a CmpU. In some cases
// the direction of this if is determined by the preceding if so it
- // can be eliminate entirely. Given an if testing (CmpI n c) check
// for an immediately control dependent if that is testing (CmpI n c2)
// and has one projection leading to this if and the other projection
// leading to a region that merges one of this ifs control
// projections.
+ //
+ // Given an if testing (CmpI n v) check for an immediately control
+ // dependent if that is testing (CmpI n v2) and has one projection
+ // leading to this if and the other projection leading to a region
+ // that merges one of this ifs control projections.
//
// If
// / |
// / |
// / |
*** 678,760 ****
--- 677,1024 ----
// /\ |
// / \ |
// / \ |
// / Region
//
Node* IfNode::fold_compares(PhaseGVN* phase) {
if (Opcode() != Op_If) return NULL;
+ // Or given an if testing (CmpI n v) check for a dominating if that is
+ // testing (CmpI n v2), both having one projection leading to an
+ // uncommon trap. Allow Another independent guard in between to cover
+ // an explicit range check:
+ // if (index < 0 || index >= array.length) {
+ // which may need a null check to guard the LoadRange
+ //
+ // If
+ // / \
+ // / \
+ // / \
+ // If unc
+ // /\
+ // / \
+ // / \
+ // / unc
+ //
Node* this_cmp = in(1)->in(1);
if (this_cmp != NULL && this_cmp->Opcode() == Op_CmpI &&
this_cmp->in(2)->is_Con() && this_cmp->in(2) != phase->C->top()) {
Node* ctrl = in(0);
BoolNode* this_bool = in(1)->as_Bool();
Node* n = this_cmp->in(1);
! int hi = this_cmp->in(2)->get_int();
if (ctrl != NULL && ctrl->is_Proj() && ctrl->outcnt() == 1 &&
+ // Is the comparison for this If suitable for folding?
+ bool IfNode::cmpi_if(PhaseIterGVN* igvn) {
+ return in(1)->is_Bool() &&
+ in(1)->in(1)->Opcode() == Op_CmpI &&
+ in(1)->in(1)->in(2) != igvn->C->top() &&
+ in(1)->as_Bool()->_test._test != BoolTest::ne &&
! in(1)->as_Bool()->_test._test != BoolTest::eq;
+ }
+
+ // Is a dominating control suitable for folding with this if?
+ bool IfNode::proj_cmpi_with(Node* ctrl, PhaseIterGVN* igvn) {
+ return ctrl != NULL &&
+ ctrl->is_Proj() &&
ctrl->in(0)->is_If() &&
ctrl->in(0)->outcnt() == 2 &&
! ctrl->in(0)->in(1)->is_Bool() &&
ctrl->in(0)->in(1)->in(1)->Opcode() == Op_CmpI &&
ctrl->in(0)->in(1)->in(1)->in(2)->is_Con() &&
ctrl->in(0)->in(1)->in(1)->in(2) != phase->C->top() &&
ctrl->in(0)->in(1)->in(1)->in(1) == n) {
IfNode* dom_iff = ctrl->in(0)->as_If();
Node* otherproj = dom_iff->proj_out(!ctrl->as_Proj()->_con);
if (otherproj->outcnt() == 1 && otherproj->unique_out()->is_Region() &&
this_bool->_test._test != BoolTest::ne && this_bool->_test._test != BoolTest::eq) {
// Identify which proj goes to the region and which continues on
! RegionNode* region = otherproj->unique_out()->as_Region();
! Node* success = NULL;
Node* fail = NULL;
! ctrl->in(0)->as_If()->cmpi_if(igvn) &&
+ // Must compare same value
+ ctrl->in(0)->in(1)->in(1)->in(1) == in(1)->in(1)->in(1);
+ }
+
+ // Do this If and the dominating If share a region?
+ bool IfNode::shared_region(ProjNode* proj, ProjNode*& success, ProjNode*& fail) {
+ ProjNode* otherproj = proj->other_if_proj();
+ Node* otherproj_ctrl_use = otherproj->unique_ctrl_out();
+ RegionNode* region = (otherproj_ctrl_use != NULL && otherproj_ctrl_use->is_Region()) ? otherproj_ctrl_use->as_Region() : NULL;
! success = NULL;
! fail = NULL;
+
+ if (otherproj->outcnt() == 1 && region != NULL && !region->has_phi()) {
for (int i = 0; i < 2; i++) {
! Node* proj = proj_out(i);
! ProjNode* proj = proj_out(i);
if (success == NULL && proj->outcnt() == 1 && proj->unique_out() == region) {
success = proj;
} else if (fail == NULL) {
fail = proj;
} else {
success = fail = NULL;
}
}
if (success != NULL && fail != NULL && !region->has_phi()) {
! int lo = dom_iff->in(1)->in(1)->in(2)->get_int();
+ }
! return success != NULL && fail != NULL;
+ }
+
+ // Return projection that leads to an uncommon trap if any
+ ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call) const {
+ for (int i = 0; i < 2; i++) {
+ call = proj_out(i)->is_uncommon_trap_proj(Deoptimization::Reason_none);
+ if (call != NULL) {
+ return proj_out(i);
+ }
+ }
+ return NULL;
+ }
+
+ // Do this If and the dominating If both branch out to an uncommon trap
+ bool IfNode::uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNode*& fail, PhaseIterGVN* igvn) {
+ ProjNode* otherproj = proj->other_if_proj();
+ CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(Deoptimization::Reason_none);
+
+ if (otherproj->outcnt() == 1 && dom_unc != NULL) {
+ CallStaticJavaNode* unc = NULL;
+ ProjNode* unc_proj = uncommon_trap_proj(unc);
+ if (unc_proj != NULL && unc_proj->outcnt() == 1) {
+ if (dom_unc == unc) {
+ // Allow the uncommon trap to be shared through a region
+ RegionNode* r = unc->in(0)->as_Region();
+ if (r->outcnt() != 2 || r->req() != 3 || r->find_edge(otherproj) == -1 || r->find_edge(unc_proj) == -1) {
+ return false;
+ }
+ assert(r->has_phi() == NULL, "simple region shouldn't have a phi");
+ } else if (dom_unc->in(0) != otherproj || unc->in(0) != unc_proj) {
+ return false;
+ }
+ // See merge_uncommon_traps: the reason of the uncmmon trap will
+ // be changed and the state of the dominating If will be
+ // used. Checked that we didn't apply this transformation in a
+ // previous compilation and it didn't cause too many traps
+ if (!igvn->C->too_many_traps(dom_unc->jvms()->method(), dom_unc->jvms()->bci(), Deoptimization::Reason_unstable_fused_if) &&
+ !igvn->C->too_many_traps(dom_unc->jvms()->method(), dom_unc->jvms()->bci(), Deoptimization::Reason_range_check)) {
+ success = unc_proj;
+ fail = unc_proj->other_if_proj();
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ // Check that the 2 CmpI can be folded into as single CmpU and proceed with the folding
+ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn) {
+ Node* this_cmp = in(1)->in(1);
+ BoolNode* this_bool = in(1)->as_Bool();
+ IfNode* dom_iff = proj->in(0)->as_If();
BoolNode* dom_bool = dom_iff->in(1)->as_Bool();
! Node* dom_cmp = dom_bool->in(1);
! const TypeInt* failtype = filtered_int_type(phase, n, ctrl);
! Node* lo = dom_iff->in(1)->in(1)->in(2);
! Node* hi = this_cmp->in(2);
+ Node* n = this_cmp->in(1);
+ ProjNode* otherproj = proj->other_if_proj();
+
+ const TypeInt* lo_type = IfNode::filtered_int_type(igvn, n, otherproj);
+ const TypeInt* hi_type = IfNode::filtered_int_type(igvn, n, success);
+
+ BoolTest::mask lo_test = dom_bool->_test._test;
+ BoolTest::mask hi_test = this_bool->_test._test;
+ BoolTest::mask cond = hi_test;
+
+ // Figure out which of the two tests sets the upper bound and which
+ // sets the lower bound if any.
+ if (hi_type->_lo > lo_type->_hi && hi_type->_hi == max_jint && lo_type->_lo == min_jint) {
+
+ assert(((lo_test == BoolTest::le || lo_test == BoolTest::lt) && !proj->_con) ||
+ ((lo_test == BoolTest::ge || lo_test == BoolTest::gt) && proj->_con), "incorrect test");
+ // this test was canonicalized
+ assert((hi_test == BoolTest::le || hi_test == BoolTest::lt) && fail->_con, "incorrect test");
+
+ if (lo_test == BoolTest::gt || lo_test == BoolTest::le) {
+ lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
+ }
+ } else if (lo_type->_lo > hi_type->_hi && lo_type->_hi == max_jint && hi_type->_lo == min_jint) {
+ swap(lo, hi);
+ swap(lo_type, hi_type);
+ swap(lo_test, hi_test);
+
+ assert(((hi_test == BoolTest::le || hi_test == BoolTest::lt) && proj->_con) ||
+ ((hi_test == BoolTest::ge || hi_test == BoolTest::gt) && !proj->_con), "incorrect test");
+ // this test was canonicalized
+ assert((lo_test == BoolTest::le || lo_test == BoolTest::lt) && !fail->_con, "incorrect test");
+
+ cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge;
+
+ if (lo_test == BoolTest::le) {
+ lo = igvn->transform(new AddINode(lo, igvn->intcon(1)));
+ }
+
+ } else {
+ const TypeInt* failtype = filtered_int_type(igvn, n, proj);
if (failtype != NULL) {
! const TypeInt* type2 = filtered_int_type(phase, n, fail);
! const TypeInt* type2 = filtered_int_type(igvn, n, fail);
if (type2 != NULL) {
failtype = failtype->join(type2)->is_int();
! } else {
failtype = NULL;
! if (failtype->_lo > failtype->_hi) {
+ // previous if determines the result of this if so
+ // replace Bool with constant
+ igvn->hash_delete(this);
+ set_req(1, igvn->intcon(success->_con));
+ return true;
+ }
}
}
if (failtype != NULL &&
dom_bool->_test._test != BoolTest::ne && dom_bool->_test._test != BoolTest::eq) {
int bound = failtype->_hi - failtype->_lo + 1;
if (failtype->_hi != max_jint && failtype->_lo != min_jint && bound > 1) {
// Merge the two compares into a single unsigned compare by building (CmpU (n - lo) hi)
BoolTest::mask cond = fail->as_Proj()->_con ? BoolTest::lt : BoolTest::ge;
! Node* adjusted = phase->transform(new SubINode(n, phase->intcon(failtype->_lo)));
! Node* newcmp = phase->transform(new CmpUNode(adjusted, phase->intcon(bound)));
! Node* newbool = phase->transform(new BoolNode(newcmp, cond));
! phase->is_IterGVN()->replace_input_of(dom_iff, 1, phase->intcon(ctrl->as_Proj()->_con));
phase->hash_delete(this);
+ lo = NULL;
+ hi = NULL;
+ }
+
+ if (lo && hi) {
+ // Merge the two compares into a single unsigned compare by building (CmpU (n - lo) (hi - lo))
! Node* adjusted_val = igvn->transform(new SubINode(n, lo));
! Node* adjusted_lim = igvn->transform(new SubINode(hi, lo));
! Node* newcmp = igvn->transform(new CmpUNode(adjusted_val, adjusted_lim));
! Node* newbool = igvn->transform(new BoolNode(newcmp, cond));
+
+ igvn->is_IterGVN()->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con));
+ igvn->hash_delete(this);
set_req(1, newbool);
return this;
+
+ return true;
+ }
+ return false;
+ }
+
+ // Merge the branches that trap for this If and the dominating If into
+ // a single region that branches to the uncommon trap for the
+ // dominating If
+ void IfNode::merge_uncommon_traps(ProjNode* proj, ProjNode* success, PhaseIterGVN* igvn) {
+ ProjNode* otherproj = proj->other_if_proj();
+
+ CallStaticJavaNode* unc = success->is_uncommon_trap_proj(Deoptimization::Reason_none);
+ CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(Deoptimization::Reason_none);
+
+ if (unc != dom_unc) {
+ Node* r = new RegionNode(3);
+
+ r->set_req(1, otherproj);
+ r->set_req(2, success);
+ r = igvn->transform(r);
+ assert(r->is_Region(), "can't go away");
+
+ // Make both If trap at the state of the first If: once the CmpI
+ // nodes are merged, if we trap we don't know which of the CmpI
+ // nodes would have caused the trap so we have to restart
+ // execution at the first one
+ igvn->replace_input_of(dom_unc, 0, r);
+ igvn->replace_input_of(unc, 0, igvn->C->top());
+ }
+ int trap_request = dom_unc->uncommon_trap_request();
+ Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request);
+ Deoptimization::DeoptAction action = Deoptimization::trap_request_action(trap_request);
+ if (success->in(0)->as_If()->range_check_trap_proj() != NULL) {
+ // If this looks like a range check, change the trap to
+ // Reason_range_check so the compiler recognizes it as a range
+ // check and applies the corresponding optimizations
+ trap_request = Deoptimization::make_trap_request(Deoptimization::Reason_range_check, action);
+ } else if (unc != dom_unc) {
+ // If we trap we won't know what CmpI would have caused the trap
+ // so use a special trap reason to mark this pair of CmpI nodes as
+ // bad candidate for folding. On recompilation we won't fold them
+ // and we may trap again but this time we'll know what branch
+ // traps
+ trap_request = Deoptimization::make_trap_request(Deoptimization::Reason_unstable_fused_if, action);
+ }
+ igvn->replace_input_of(dom_unc, TypeFunc::Parms, igvn->intcon(trap_request));
+ }
+
+ // Check that the If that is in between the 2 integer comparisons has
+ // no side effect
+ bool IfNode::side_effect_free(ProjNode* proj, PhaseIterGVN* igvn) {
+ if (proj != NULL &&
+ proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) &&
+ proj->outcnt() <= 2) {
+ Node* this_cmp = in(1)->in(1);
+ Node* other = this_cmp->in(2);
+ if (proj->outcnt() == 1 ||
+ // Allow simple null check from LoadRange
+ (other->Opcode() == Op_LoadRange &&
+ ((other->in(0) != NULL && other->in(0) == proj) ||
+ (other->in(0) == NULL && other->in(2)->is_AddP() && other->in(2)->in(1)->Opcode() == Op_CastPP && other->in(2)->in(1)->in(0) == proj)))) {
+ CallStaticJavaNode* unc = proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
+ CallStaticJavaNode* dom_unc = proj->in(0)->in(0)->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
+
+ // reroute_side_effect_free_unc changes the state of this
+ // uncommon trap to restart execution at the previous
+ // CmpI. Check that this change in a previous compilation didn't
+ // cause too many traps.
+ int trap_request = unc->uncommon_trap_request();
+ Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request);
+
+ if (igvn->C->too_many_traps(dom_unc->jvms()->method(), dom_unc->jvms()->bci(), reason)) {
+ return false;
+ }
+
+ return true;
}
if (failtype->_lo > failtype->_hi) {
// previous if determines the result of this if so
// replace Bool with constant
phase->hash_delete(this);
set_req(1, phase->intcon(success->as_Proj()->_con));
return this;
}
+ return false;
+ }
+
+ // Make the If between the 2 integer comparisons trap at the state of
+ // the first If: the last CmpI is the one replaced by a CmpU and the
+ // first CmpI is eliminated, so the test between the 2 CmpI nodes
+ // won't be guarded by the first CmpI anymore. It can trap in cases
+ // where the first CmpI would have prevented it from executing: on a
+ // trap, we need to restart execution at the state of the first CmpI
+ void IfNode::reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn) {
+ CallStaticJavaNode* dom_unc = dom_proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
+ ProjNode* otherproj = proj->other_if_proj();
+ CallStaticJavaNode* unc = proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none);
+
+ CallStaticJavaNode* new_unc = dom_unc->clone()->as_CallStaticJava();
+ Node* call_proj = dom_unc->unique_ctrl_out();
+ Node* halt = call_proj->unique_ctrl_out();
+
+ call_proj = call_proj->clone();
+ halt = halt->clone();
+ Node* c = otherproj->clone();
+ new_unc->set_req(TypeFunc::Parms, unc->in(TypeFunc::Parms));
+ new_unc->set_req(0, c);
+ call_proj->set_req(0, new_unc);
+ halt->set_req(0, call_proj);
+
+ igvn->replace_node(otherproj, igvn->C->top());
+
+ igvn->transform(c);
+ igvn->transform(new_unc);
+ igvn->transform(call_proj);
+ igvn->transform(halt);
+
+ igvn->C->root()->add_req(halt);
+ }
+
+ Node* IfNode::fold_compares(PhaseIterGVN* igvn) {
+ if (Opcode() != Op_If) return NULL;
+
+ if (cmpi_if(igvn)) {
+ Node* ctrl = in(0);
+ if (proj_cmpi_with(ctrl, igvn) &&
+ ctrl->outcnt() == 1) {
+ // A integer comparison immediately dominated by another integer
+ // comparison
+ ProjNode* success = NULL;
+ ProjNode* fail = NULL;
+ ProjNode* dom_cmp = ctrl->as_Proj();
+ if (shared_region(dom_cmp, success, fail) &&
+ // Next call modifies graph so must be last
+ fold_compares_helper(dom_cmp, success, fail, igvn)) {
+ return this;
}
+ if (uncommon_traps(dom_cmp, success, fail, igvn) &&
+ // Next call modifies graph so must be last
+ fold_compares_helper(dom_cmp, success, fail, igvn)) {
+ merge_uncommon_traps(dom_cmp, success, igvn);
+ return this;
}
+ return NULL;
+ } else {
+ ProjNode* success = NULL;
+ ProjNode* fail = NULL;
+ Node* dom = ctrl->in(0)->in(0);
+ ProjNode* dom_cmp = dom->isa_Proj();
+ ProjNode* other_cmp = ctrl->isa_Proj();
+
+ // Check if it's an integer comparison dominated by another
+ // integer comparison with another test in between
+ if (proj_cmpi_with(dom, igvn) &&
+ uncommon_traps(dom_cmp, success, fail, igvn) &&
+ side_effect_free(other_cmp, igvn) &&
+ // Next call modifies graph so must be last
+ fold_compares_helper(dom_cmp, success, fail, igvn)) {
+ reroute_side_effect_free_unc(other_cmp, dom_cmp, igvn);
+ merge_uncommon_traps(dom_cmp, success, igvn);
+ return this;
}
}
}
return NULL;
}
*** 1027,1037 ****
--- 1291,1301 ----
}
// Normal equivalent-test check.
if( !dom ) return NULL; // Dead loop?
! Node* result = fold_compares(phase);
! Node* result = fold_compares(igvn);
if (result != NULL) {
return result;
}
// Search up the dominator tree for an If with an identical test
*** 1087,1097 ****
--- 1351,1361 ----
// Loop predicates may have depending checks which should not
// be skipped. For example, range check predicate has two checks
// for lower and upper bounds.
ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj();
! if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL)
prev_dom = idom;
// Now walk the current IfNode's projections.
// Loop ends when 'this' has no more uses.
for (DUIterator_Last imin, i = last_outs(imin); i >= imin; --i) {
src/share/vm/opto/ifnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File