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?