src/share/vm/opto/ifnode.cpp

changeset 452
ff5961f4c095
parent 435
a61af66fc99e
child 685
6ca61c728c2d
     1.1 --- a/src/share/vm/opto/ifnode.cpp	Wed Dec 05 09:00:00 2007 -0800
     1.2 +++ b/src/share/vm/opto/ifnode.cpp	Wed Dec 05 09:01:00 2007 -0800
     1.3 @@ -543,6 +543,159 @@
     1.4    return NULL;                  // Dead loop?  Or hit root?
     1.5  }
     1.6  
     1.7 +
     1.8 +//------------------------------filtered_int_type--------------------------------
     1.9 +// Return a possibly more restrictive type for val based on condition control flow for an if
    1.10 +const TypeInt* IfNode::filtered_int_type(PhaseGVN* gvn, Node *val, Node* if_proj) {
    1.11 +  assert(if_proj &&
    1.12 +         (if_proj->Opcode() == Op_IfTrue || if_proj->Opcode() == Op_IfFalse), "expecting an if projection");
    1.13 +  if (if_proj->in(0) && if_proj->in(0)->is_If()) {
    1.14 +    IfNode* iff = if_proj->in(0)->as_If();
    1.15 +    if (iff->in(1) && iff->in(1)->is_Bool()) {
    1.16 +      BoolNode* bol = iff->in(1)->as_Bool();
    1.17 +      if (bol->in(1) && bol->in(1)->is_Cmp()) {
    1.18 +        const CmpNode* cmp  = bol->in(1)->as_Cmp();
    1.19 +        if (cmp->in(1) == val) {
    1.20 +          const TypeInt* cmp2_t = gvn->type(cmp->in(2))->isa_int();
    1.21 +          if (cmp2_t != NULL) {
    1.22 +            jint lo = cmp2_t->_lo;
    1.23 +            jint hi = cmp2_t->_hi;
    1.24 +            BoolTest::mask msk = if_proj->Opcode() == Op_IfTrue ? bol->_test._test : bol->_test.negate();
    1.25 +            switch (msk) {
    1.26 +            case BoolTest::ne:
    1.27 +              // Can't refine type
    1.28 +              return NULL;
    1.29 +            case BoolTest::eq:
    1.30 +              return cmp2_t;
    1.31 +            case BoolTest::lt:
    1.32 +              lo = TypeInt::INT->_lo;
    1.33 +              if (hi - 1 < hi) {
    1.34 +                hi = hi - 1;
    1.35 +              }
    1.36 +              break;
    1.37 +            case BoolTest::le:
    1.38 +              lo = TypeInt::INT->_lo;
    1.39 +              break;
    1.40 +            case BoolTest::gt:
    1.41 +              if (lo + 1 > lo) {
    1.42 +                lo = lo + 1;
    1.43 +              }
    1.44 +              hi = TypeInt::INT->_hi;
    1.45 +              break;
    1.46 +            case BoolTest::ge:
    1.47 +              // lo unchanged
    1.48 +              hi = TypeInt::INT->_hi;
    1.49 +              break;
    1.50 +            }
    1.51 +            const TypeInt* rtn_t = TypeInt::make(lo, hi, cmp2_t->_widen);
    1.52 +            return rtn_t;
    1.53 +          }
    1.54 +        }
    1.55 +      }
    1.56 +    }
    1.57 +  }
    1.58 +  return NULL;
    1.59 +}
    1.60 +
    1.61 +//------------------------------fold_compares----------------------------
    1.62 +// See if a pair of CmpIs can be converted into a CmpU.  In some cases
    1.63 +// the direction of this if is determined by the preciding if so it
    1.64 +// can be eliminate entirely.  Given an if testing (CmpI n c) check
    1.65 +// for an immediately control dependent if that is testing (CmpI n c2)
    1.66 +// and has one projection leading to this if and the other projection
    1.67 +// leading to a region that merges one of this ifs control
    1.68 +// projections.
    1.69 +//
    1.70 +//                   If
    1.71 +//                  / |
    1.72 +//                 /  |
    1.73 +//                /   |
    1.74 +//              If    |
    1.75 +//              /\    |
    1.76 +//             /  \   |
    1.77 +//            /    \  |
    1.78 +//           /    Region
    1.79 +//
    1.80 +Node* IfNode::fold_compares(PhaseGVN* phase) {
    1.81 +  if (!EliminateAutoBox || Opcode() != Op_If) return NULL;
    1.82 +
    1.83 +  Node* this_cmp = in(1)->in(1);
    1.84 +  if (this_cmp != NULL && this_cmp->Opcode() == Op_CmpI &&
    1.85 +      this_cmp->in(2)->is_Con() && this_cmp->in(2) != phase->C->top()) {
    1.86 +    Node* ctrl = in(0);
    1.87 +    BoolNode* this_bool = in(1)->as_Bool();
    1.88 +    Node* n = this_cmp->in(1);
    1.89 +    int hi = this_cmp->in(2)->get_int();
    1.90 +    if (ctrl != NULL && ctrl->is_Proj() && ctrl->outcnt() == 1 &&
    1.91 +        ctrl->in(0)->is_If() &&
    1.92 +        ctrl->in(0)->outcnt() == 2 &&
    1.93 +        ctrl->in(0)->in(1)->is_Bool() &&
    1.94 +        ctrl->in(0)->in(1)->in(1)->Opcode() == Op_CmpI &&
    1.95 +        ctrl->in(0)->in(1)->in(1)->in(2)->is_Con() &&
    1.96 +        ctrl->in(0)->in(1)->in(1)->in(1) == n) {
    1.97 +      IfNode* dom_iff = ctrl->in(0)->as_If();
    1.98 +      Node* otherproj = dom_iff->proj_out(!ctrl->as_Proj()->_con);
    1.99 +      if (otherproj->outcnt() == 1 && otherproj->unique_out()->is_Region() &&
   1.100 +          this_bool->_test._test != BoolTest::ne && this_bool->_test._test != BoolTest::eq) {
   1.101 +        // Identify which proj goes to the region and which continues on
   1.102 +        RegionNode* region = otherproj->unique_out()->as_Region();
   1.103 +        Node* success = NULL;
   1.104 +        Node* fail = NULL;
   1.105 +        for (int i = 0; i < 2; i++) {
   1.106 +          Node* proj = proj_out(i);
   1.107 +          if (success == NULL && proj->outcnt() == 1 && proj->unique_out() == region) {
   1.108 +            success = proj;
   1.109 +          } else if (fail == NULL) {
   1.110 +            fail = proj;
   1.111 +          } else {
   1.112 +            success = fail = NULL;
   1.113 +          }
   1.114 +        }
   1.115 +        if (success != NULL && fail != NULL && !region->has_phi()) {
   1.116 +          int lo = dom_iff->in(1)->in(1)->in(2)->get_int();
   1.117 +          BoolNode* dom_bool = dom_iff->in(1)->as_Bool();
   1.118 +          Node* dom_cmp =  dom_bool->in(1);
   1.119 +          const TypeInt* failtype  = filtered_int_type(phase, n, ctrl);
   1.120 +          if (failtype != NULL) {
   1.121 +            const TypeInt* type2 = filtered_int_type(phase, n, fail);
   1.122 +            if (type2 != NULL) {
   1.123 +              failtype = failtype->join(type2)->is_int();
   1.124 +            } else {
   1.125 +              failtype = NULL;
   1.126 +            }
   1.127 +          }
   1.128 +
   1.129 +          if (failtype != NULL &&
   1.130 +              dom_bool->_test._test != BoolTest::ne && dom_bool->_test._test != BoolTest::eq) {
   1.131 +            int bound = failtype->_hi - failtype->_lo + 1;
   1.132 +            if (failtype->_hi != max_jint && failtype->_lo != min_jint && bound > 1) {
   1.133 +              // Merge the two compares into a single unsigned compare by building  (CmpU (n - lo) hi)
   1.134 +              BoolTest::mask cond = fail->as_Proj()->_con ? BoolTest::lt : BoolTest::ge;
   1.135 +              Node* adjusted = phase->transform(new (phase->C, 3) SubINode(n, phase->intcon(failtype->_lo)));
   1.136 +              Node* newcmp = phase->transform(new (phase->C, 3) CmpUNode(adjusted, phase->intcon(bound)));
   1.137 +              Node* newbool = phase->transform(new (phase->C, 2) BoolNode(newcmp, cond));
   1.138 +              phase->hash_delete(dom_iff);
   1.139 +              dom_iff->set_req(1, phase->intcon(ctrl->as_Proj()->_con));
   1.140 +              phase->is_IterGVN()->_worklist.push(dom_iff);
   1.141 +              phase->hash_delete(this);
   1.142 +              set_req(1, newbool);
   1.143 +              return this;
   1.144 +            }
   1.145 +            if (failtype->_lo > failtype->_hi) {
   1.146 +              // previous if determines the result of this if so
   1.147 +              // replace Bool with constant
   1.148 +              phase->hash_delete(this);
   1.149 +              set_req(1, phase->intcon(success->as_Proj()->_con));
   1.150 +              return this;
   1.151 +            }
   1.152 +          }
   1.153 +        }
   1.154 +      }
   1.155 +    }
   1.156 +  }
   1.157 +  return NULL;
   1.158 +}
   1.159 +
   1.160  //------------------------------remove_useless_bool----------------------------
   1.161  // Check for people making a useless boolean: things like
   1.162  // if( (x < y ? true : false) ) { ... }
   1.163 @@ -744,6 +897,11 @@
   1.164      // Normal equivalent-test check.
   1.165      if( !dom ) return NULL;     // Dead loop?
   1.166  
   1.167 +    Node* result = fold_compares(phase);
   1.168 +    if (result != NULL) {
   1.169 +      return result;
   1.170 +    }
   1.171 +
   1.172      // Search up the dominator tree for an If with an identical test
   1.173      while( dom->Opcode() != op    ||  // Not same opcode?
   1.174             dom->in(1)    != in(1) ||  // Not same input 1?

mercurial