ProjNode* mod_proj() { return proj_out(mod_proj_num); }
//------------------------------is_range_check--------------------------------- // Return 0 if not a range check. Return 1 if a range check and set index and // offset. Return 2 if we had to negate the test. Index is NULL if the check // is versus a constant. int IfNode::is_range_check(Node* &range, Node* &index, jint &offset) { Node* b = in(1); if (b == NULL || !b->is_Bool()) return 0; BoolNode* bn = b->as_Bool(); Node* cmp = bn->in(1); if (cmp == NULL) return 0; if (cmp->Opcode() != Op_CmpU) return 0; Node* l = cmp->in(1); Node* r = cmp->in(2); int flip_test = 1; if (bn->_test._test == BoolTest::le) { l = cmp->in(2); r = cmp->in(1); flip_test = 2; } else if (bn->_test._test != BoolTest::lt) { return 0; } if (l->is_top()) return 0; // Top input means dead test if (r->Opcode() != Op_LoadRange) return 0; // We have recognized one of these forms: // Flip 1: If (Bool[<] CmpU(l, LoadRange)) ... // Flip 2: If (Bool[<=] CmpU(LoadRange, l)) ... // Make sure it's a real range check by requiring an uncommon trap // along the OOB path. Otherwise, it's possible that the user wrote // something which optimized to look like a range check but behaves // in some other way. Node* iftrap = proj_out(flip_test == 2 ? true : false); bool found_trap = false; if (iftrap != NULL) { Node* u = iftrap->unique_ctrl_out(); if (u != NULL) { // It could be a merge point (Region) for uncommon trap. if (u->is_Region()) { Node* c = u->unique_ctrl_out(); if (c != NULL) { iftrap = u; u = c; } } if (u->in(0) == iftrap && u->is_CallStaticJava()) { int req = u->as_CallStaticJava()->uncommon_trap_request(); if (Deoptimization::trap_request_reason(req) == Deoptimization::Reason_range_check) { found_trap = true; } } } } if (!found_trap) return 0; // sorry, no cigar // Look for index+offset form Node* ind = l; jint off = 0; if (l->is_top()) { return 0; } else if (l->is_Add()) { if ((off = l->in(1)->find_int_con(0)) != 0) { ind = l->in(2); } else if ((off = l->in(2)->find_int_con(0)) != 0) { ind = l->in(1); } } else if ((off = l->find_int_con(-1)) >= 0) { // constant offset with no variable index ind = NULL; } else { // variable index with no constant offset (or dead negative index) off = 0; } // Return all the values: index = ind; offset = off; range = r; return flip_test; }
ProjNode* div_proj() { return proj_out(div_proj_num); }