comparison src/share/vm/opto/ifnode.cpp @ 17:ff5961f4c095

6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long) Reviewed-by: kvn, rasbold
author never
date Wed, 05 Dec 2007 09:01:00 -0800
parents a61af66fc99e
children 6ca61c728c2d
comparison
equal deleted inserted replaced
16:f8236e79048a 17:ff5961f4c095
541 541
542 // Give up the search at true merges 542 // Give up the search at true merges
543 return NULL; // Dead loop? Or hit root? 543 return NULL; // Dead loop? Or hit root?
544 } 544 }
545 545
546
547 //------------------------------filtered_int_type--------------------------------
548 // Return a possibly more restrictive type for val based on condition control flow for an if
549 const TypeInt* IfNode::filtered_int_type(PhaseGVN* gvn, Node *val, Node* if_proj) {
550 assert(if_proj &&
551 (if_proj->Opcode() == Op_IfTrue || if_proj->Opcode() == Op_IfFalse), "expecting an if projection");
552 if (if_proj->in(0) && if_proj->in(0)->is_If()) {
553 IfNode* iff = if_proj->in(0)->as_If();
554 if (iff->in(1) && iff->in(1)->is_Bool()) {
555 BoolNode* bol = iff->in(1)->as_Bool();
556 if (bol->in(1) && bol->in(1)->is_Cmp()) {
557 const CmpNode* cmp = bol->in(1)->as_Cmp();
558 if (cmp->in(1) == val) {
559 const TypeInt* cmp2_t = gvn->type(cmp->in(2))->isa_int();
560 if (cmp2_t != NULL) {
561 jint lo = cmp2_t->_lo;
562 jint hi = cmp2_t->_hi;
563 BoolTest::mask msk = if_proj->Opcode() == Op_IfTrue ? bol->_test._test : bol->_test.negate();
564 switch (msk) {
565 case BoolTest::ne:
566 // Can't refine type
567 return NULL;
568 case BoolTest::eq:
569 return cmp2_t;
570 case BoolTest::lt:
571 lo = TypeInt::INT->_lo;
572 if (hi - 1 < hi) {
573 hi = hi - 1;
574 }
575 break;
576 case BoolTest::le:
577 lo = TypeInt::INT->_lo;
578 break;
579 case BoolTest::gt:
580 if (lo + 1 > lo) {
581 lo = lo + 1;
582 }
583 hi = TypeInt::INT->_hi;
584 break;
585 case BoolTest::ge:
586 // lo unchanged
587 hi = TypeInt::INT->_hi;
588 break;
589 }
590 const TypeInt* rtn_t = TypeInt::make(lo, hi, cmp2_t->_widen);
591 return rtn_t;
592 }
593 }
594 }
595 }
596 }
597 return NULL;
598 }
599
600 //------------------------------fold_compares----------------------------
601 // See if a pair of CmpIs can be converted into a CmpU. In some cases
602 // the direction of this if is determined by the preciding if so it
603 // can be eliminate entirely. Given an if testing (CmpI n c) check
604 // for an immediately control dependent if that is testing (CmpI n c2)
605 // and has one projection leading to this if and the other projection
606 // leading to a region that merges one of this ifs control
607 // projections.
608 //
609 // If
610 // / |
611 // / |
612 // / |
613 // If |
614 // /\ |
615 // / \ |
616 // / \ |
617 // / Region
618 //
619 Node* IfNode::fold_compares(PhaseGVN* phase) {
620 if (!EliminateAutoBox || Opcode() != Op_If) return NULL;
621
622 Node* this_cmp = in(1)->in(1);
623 if (this_cmp != NULL && this_cmp->Opcode() == Op_CmpI &&
624 this_cmp->in(2)->is_Con() && this_cmp->in(2) != phase->C->top()) {
625 Node* ctrl = in(0);
626 BoolNode* this_bool = in(1)->as_Bool();
627 Node* n = this_cmp->in(1);
628 int hi = this_cmp->in(2)->get_int();
629 if (ctrl != NULL && ctrl->is_Proj() && ctrl->outcnt() == 1 &&
630 ctrl->in(0)->is_If() &&
631 ctrl->in(0)->outcnt() == 2 &&
632 ctrl->in(0)->in(1)->is_Bool() &&
633 ctrl->in(0)->in(1)->in(1)->Opcode() == Op_CmpI &&
634 ctrl->in(0)->in(1)->in(1)->in(2)->is_Con() &&
635 ctrl->in(0)->in(1)->in(1)->in(1) == n) {
636 IfNode* dom_iff = ctrl->in(0)->as_If();
637 Node* otherproj = dom_iff->proj_out(!ctrl->as_Proj()->_con);
638 if (otherproj->outcnt() == 1 && otherproj->unique_out()->is_Region() &&
639 this_bool->_test._test != BoolTest::ne && this_bool->_test._test != BoolTest::eq) {
640 // Identify which proj goes to the region and which continues on
641 RegionNode* region = otherproj->unique_out()->as_Region();
642 Node* success = NULL;
643 Node* fail = NULL;
644 for (int i = 0; i < 2; i++) {
645 Node* proj = proj_out(i);
646 if (success == NULL && proj->outcnt() == 1 && proj->unique_out() == region) {
647 success = proj;
648 } else if (fail == NULL) {
649 fail = proj;
650 } else {
651 success = fail = NULL;
652 }
653 }
654 if (success != NULL && fail != NULL && !region->has_phi()) {
655 int lo = dom_iff->in(1)->in(1)->in(2)->get_int();
656 BoolNode* dom_bool = dom_iff->in(1)->as_Bool();
657 Node* dom_cmp = dom_bool->in(1);
658 const TypeInt* failtype = filtered_int_type(phase, n, ctrl);
659 if (failtype != NULL) {
660 const TypeInt* type2 = filtered_int_type(phase, n, fail);
661 if (type2 != NULL) {
662 failtype = failtype->join(type2)->is_int();
663 } else {
664 failtype = NULL;
665 }
666 }
667
668 if (failtype != NULL &&
669 dom_bool->_test._test != BoolTest::ne && dom_bool->_test._test != BoolTest::eq) {
670 int bound = failtype->_hi - failtype->_lo + 1;
671 if (failtype->_hi != max_jint && failtype->_lo != min_jint && bound > 1) {
672 // Merge the two compares into a single unsigned compare by building (CmpU (n - lo) hi)
673 BoolTest::mask cond = fail->as_Proj()->_con ? BoolTest::lt : BoolTest::ge;
674 Node* adjusted = phase->transform(new (phase->C, 3) SubINode(n, phase->intcon(failtype->_lo)));
675 Node* newcmp = phase->transform(new (phase->C, 3) CmpUNode(adjusted, phase->intcon(bound)));
676 Node* newbool = phase->transform(new (phase->C, 2) BoolNode(newcmp, cond));
677 phase->hash_delete(dom_iff);
678 dom_iff->set_req(1, phase->intcon(ctrl->as_Proj()->_con));
679 phase->is_IterGVN()->_worklist.push(dom_iff);
680 phase->hash_delete(this);
681 set_req(1, newbool);
682 return this;
683 }
684 if (failtype->_lo > failtype->_hi) {
685 // previous if determines the result of this if so
686 // replace Bool with constant
687 phase->hash_delete(this);
688 set_req(1, phase->intcon(success->as_Proj()->_con));
689 return this;
690 }
691 }
692 }
693 }
694 }
695 }
696 return NULL;
697 }
698
546 //------------------------------remove_useless_bool---------------------------- 699 //------------------------------remove_useless_bool----------------------------
547 // Check for people making a useless boolean: things like 700 // Check for people making a useless boolean: things like
548 // if( (x < y ? true : false) ) { ... } 701 // if( (x < y ? true : false) ) { ... }
549 // Replace with if( x < y ) { ... } 702 // Replace with if( x < y ) { ... }
550 static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) { 703 static Node *remove_useless_bool(IfNode *iff, PhaseGVN *phase) {
742 } 895 }
743 896
744 // Normal equivalent-test check. 897 // Normal equivalent-test check.
745 if( !dom ) return NULL; // Dead loop? 898 if( !dom ) return NULL; // Dead loop?
746 899
900 Node* result = fold_compares(phase);
901 if (result != NULL) {
902 return result;
903 }
904
747 // Search up the dominator tree for an If with an identical test 905 // Search up the dominator tree for an If with an identical test
748 while( dom->Opcode() != op || // Not same opcode? 906 while( dom->Opcode() != op || // Not same opcode?
749 dom->in(1) != in(1) || // Not same input 1? 907 dom->in(1) != in(1) || // Not same input 1?
750 (req() == 3 && dom->in(2) != in(2)) || // Not same input 2? 908 (req() == 3 && dom->in(2) != in(2)) || // Not same input 2?
751 prev_dom->in(0) != dom ) { // One path of test does not dominate? 909 prev_dom->in(0) != dom ) { // One path of test does not dominate?