Mercurial > hg > truffle
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? |