src/share/vm/opto/ifnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/opto/ifnode.cpp

src/share/vm/opto/ifnode.cpp

Print this page
rev 8161 : 8078426: mb/jvm/compiler/InterfaceCalls/testAC2 - assert(predicate_proj == 0L) failed: only one predicate entry expected
Summary: split if finds predicates on several incoming paths when unswitched's loops are optimized out
Reviewed-by:
rev 8576 : 8081823: C2 performs unsigned comparison against -1
Summary: x <= 0 || x > 0 wrongly folded as (x-1) >u -1
Reviewed-by:

*** 815,837 **** 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((dom_bool->_test.is_less() && !proj->_con) || (dom_bool->_test.is_greater() && proj->_con), "incorrect test"); // this test was canonicalized assert(this_bool->_test.is_less() && 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((dom_bool->_test.is_less() && proj->_con) || --- 815,896 ---- BoolTest::mask lo_test = dom_bool->_test._test; BoolTest::mask hi_test = this_bool->_test._test; BoolTest::mask cond = hi_test; + // convert: + // + // dom_bool = x {<,<=,>,>=} a + // / \ + // proj = {True, False} / \ otherproj = {False,True} + // / + // this_bool = x {<,<=} b + // / \ + // fail = {True, False} / \ success = {False,True} + // / + // + // (Second test guaranteed canonicalized, first one may not have + // been canonicalized yet) + // + // into: + // + // cond = (x - lo) {<u,<=u,>u,>=u} adjusted_lim + // / \ + // fail / \ success + // / + // + // Figure out which of the two tests sets the upper bound and which // sets the lower bound if any. + Node* adjusted_lim = NULL; if (hi_type->_lo > lo_type->_hi && hi_type->_hi == max_jint && lo_type->_lo == min_jint) { assert((dom_bool->_test.is_less() && !proj->_con) || (dom_bool->_test.is_greater() && proj->_con), "incorrect test"); // this test was canonicalized assert(this_bool->_test.is_less() && fail->_con, "incorrect test"); + // this_bool = < + // dom_bool = >= (proj = True) or dom_bool = < (proj = False) + // x in [a, b[ on the fail (= True) projection, b > a-1 (because of hi_type->_lo > lo_type->_hi test above): + // lo = a, hi = b, adjusted_lim = b-a, cond = <u + // dom_bool = > (proj = True) or dom_bool = <= (proj = False) + // x in ]a, b[ on the fail (= True) projection, b > a: + // lo = a+1, hi = b, adjusted_lim = b-a-1, cond = <u + // this_bool = <= + // dom_bool = >= (proj = True) or dom_bool = < (proj = False) + // x in [a, b] on the fail (= True) projection, b+1 > a-1: + // lo = a, hi = b, adjusted_lim = b-a, cond = <=u + // dom_bool = > (proj = True) or dom_bool = <= (proj = False) + // x in ]a, b] on the fail (= True) projection b+1 > a: + // lo = a+1, hi = b, adjusted_lim = b-a, cond = <u + // lo = a+1, hi = b, adjusted_lim = b-a-1, cond = <=u doesn't work because a = b is possible, then hi-lo = -1 + if (lo_test == BoolTest::gt || lo_test == BoolTest::le) { + if (hi_test == BoolTest::le) { + adjusted_lim = igvn->transform(new SubINode(hi, lo)); + cond = BoolTest::lt; + } 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) { + + // this_bool = < + // dom_bool = < (proj = True) or dom_bool = >= (proj = False) + // x in non empty [b, a[ on the fail (= False) projection, a > b-1 (because of lo_type->_lo > hi_type->_hi above): + // lo = b, hi = a, adjusted_lim = a-b, cond = >=u + // dom_bool = <= (proj = True) or dom_bool = > (proj = False) + // x in non empty [b, a] on the fail (= False) projection, a+1 > b-1: + // lo = b, hi = a, adjusted_lim = a-b, cond = >u + // this_bool = <= + // dom_bool = < (proj = True) or dom_bool = >= (proj = False) + // x in non empty ]b, a[ on the fail (= False) projection, a > b: + // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >=u + // dom_bool = <= (proj = True) or dom_bool = > (proj = False) + // x in non empty ]b, a] on the fail (= False) projection, a+1 > b: + // lo = b+1, hi = a, adjusted_lim = a-b, cond = >=u + // lo = b+1, hi = a, adjusted_lim = a-b-1, cond = >u doesn't work because a = b is possible, then hi-lo = -1 + swap(lo, hi); swap(lo_type, hi_type); swap(lo_test, hi_test); assert((dom_bool->_test.is_less() && proj->_con) ||
*** 840,849 **** --- 899,912 ---- assert(this_bool->_test.is_less() && !fail->_con, "incorrect test"); cond = (hi_test == BoolTest::le || hi_test == BoolTest::gt) ? BoolTest::gt : BoolTest::ge; if (lo_test == BoolTest::le) { + if (cond == BoolTest::gt) { + adjusted_lim = igvn->transform(new SubINode(hi, lo)); + cond = BoolTest::ge; + } lo = igvn->transform(new AddINode(lo, igvn->intcon(1))); } } else { const TypeInt* failtype = filtered_int_type(igvn, n, proj);
*** 858,881 **** set_req(1, igvn->intcon(success->_con)); return true; } } } - 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 true; } return false; --- 921,944 ---- set_req(1, igvn->intcon(success->_con)); return true; } } } 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)); ! if (adjusted_lim == NULL) { ! 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->replace_input_of(dom_iff, 1, igvn->intcon(proj->_con)); set_req(1, newbool); return true; } return false;
src/share/vm/opto/ifnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File