diff -r a4ffa2fa7f4d -r 9ebfec283f56 hotspot/src/share/vm/opto/library_call.cpp --- a/hotspot/src/share/vm/opto/library_call.cpp Wed Dec 23 16:24:19 2015 -0800 +++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Dec 23 21:09:50 2015 -0800 @@ -230,8 +230,6 @@ bool inline_math_negateExactL(); bool inline_math_subtractExactI(bool is_decrement); bool inline_math_subtractExactL(bool is_decrement); - bool inline_pow(); - Node* finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName); bool inline_min_max(vmIntrinsics::ID id); bool inline_notify(vmIntrinsics::ID id); Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); @@ -1718,243 +1716,6 @@ return true; } -Node* LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName) { - //------------------- - //result=(result.isNaN())? funcAddr():result; - // Check: If isNaN() by checking result!=result? then either trap - // or go to runtime - Node* cmpisnan = _gvn.transform(new CmpDNode(result, result)); - // Build the boolean node - Node* bolisnum = _gvn.transform(new BoolNode(cmpisnan, BoolTest::eq)); - - if (!too_many_traps(Deoptimization::Reason_intrinsic)) { - { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); - // The pow or exp intrinsic returned a NaN, which requires a call - // to the runtime. Recompile with the runtime call. - uncommon_trap(Deoptimization::Reason_intrinsic, - Deoptimization::Action_make_not_entrant); - } - return result; - } else { - // If this inlining ever returned NaN in the past, we compile a call - // to the runtime to properly handle corner cases - - IfNode* iff = create_and_xform_if(control(), bolisnum, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); - Node* if_slow = _gvn.transform(new IfFalseNode(iff)); - Node* if_fast = _gvn.transform(new IfTrueNode(iff)); - - if (!if_slow->is_top()) { - RegionNode* result_region = new RegionNode(3); - PhiNode* result_val = new PhiNode(result_region, Type::DOUBLE); - - result_region->init_req(1, if_fast); - result_val->init_req(1, result); - - set_control(if_slow); - - const TypePtr* no_memory_effects = NULL; - Node* rt = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName, - no_memory_effects, - x, top(), y, y ? top() : NULL); - Node* value = _gvn.transform(new ProjNode(rt, TypeFunc::Parms+0)); -#ifdef ASSERT - Node* value_top = _gvn.transform(new ProjNode(rt, TypeFunc::Parms+1)); - assert(value_top == top(), "second value must be top"); -#endif - - result_region->init_req(2, control()); - result_val->init_req(2, value); - set_control(_gvn.transform(result_region)); - return _gvn.transform(result_val); - } else { - return result; - } - } -} - -//------------------------------inline_pow------------------------------------- -// Inline power instructions, if possible. -bool LibraryCallKit::inline_pow() { - // Pseudocode for pow - // if (y == 2) { - // return x * x; - // } else { - // if (x <= 0.0) { - // long longy = (long)y; - // if ((double)longy == y) { // if y is long - // if (y + 1 == y) longy = 0; // huge number: even - // result = ((1&longy) == 0)?-DPow(abs(x), y):DPow(abs(x), y); - // } else { - // result = NaN; - // } - // } else { - // result = DPow(x,y); - // } - // if (result != result)? { - // result = uncommon_trap() or runtime_call(); - // } - // return result; - // } - - Node* x = round_double_node(argument(0)); - Node* y = round_double_node(argument(2)); - - Node* result = NULL; - - Node* const_two_node = makecon(TypeD::make(2.0)); - Node* cmp_node = _gvn.transform(new CmpDNode(y, const_two_node)); - Node* bool_node = _gvn.transform(new BoolNode(cmp_node, BoolTest::eq)); - IfNode* if_node = create_and_xform_if(control(), bool_node, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); - Node* if_true = _gvn.transform(new IfTrueNode(if_node)); - Node* if_false = _gvn.transform(new IfFalseNode(if_node)); - - RegionNode* region_node = new RegionNode(3); - region_node->init_req(1, if_true); - - Node* phi_node = new PhiNode(region_node, Type::DOUBLE); - // special case for x^y where y == 2, we can convert it to x * x - phi_node->init_req(1, _gvn.transform(new MulDNode(x, x))); - - // set control to if_false since we will now process the false branch - set_control(if_false); - - if (!too_many_traps(Deoptimization::Reason_intrinsic)) { - // Short form: skip the fancy tests and just check for NaN result. - result = _gvn.transform(new PowDNode(C, control(), x, y)); - } else { - // If this inlining ever returned NaN in the past, include all - // checks + call to the runtime. - - // Set the merge point for If node with condition of (x <= 0.0) - // There are four possible paths to region node and phi node - RegionNode *r = new RegionNode(4); - Node *phi = new PhiNode(r, Type::DOUBLE); - - // Build the first if node: if (x <= 0.0) - // Node for 0 constant - Node *zeronode = makecon(TypeD::ZERO); - // Check x:0 - Node *cmp = _gvn.transform(new CmpDNode(x, zeronode)); - // Check: If (x<=0) then go complex path - Node *bol1 = _gvn.transform(new BoolNode( cmp, BoolTest::le )); - // Branch either way - IfNode *if1 = create_and_xform_if(control(),bol1, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); - // Fast path taken; set region slot 3 - Node *fast_taken = _gvn.transform(new IfFalseNode(if1)); - r->init_req(3,fast_taken); // Capture fast-control - - // Fast path not-taken, i.e. slow path - Node *complex_path = _gvn.transform(new IfTrueNode(if1)); - - // Set fast path result - Node *fast_result = _gvn.transform(new PowDNode(C, control(), x, y)); - phi->init_req(3, fast_result); - - // Complex path - // Build the second if node (if y is long) - // Node for (long)y - Node *longy = _gvn.transform(new ConvD2LNode(y)); - // Node for (double)((long) y) - Node *doublelongy= _gvn.transform(new ConvL2DNode(longy)); - // Check (double)((long) y) : y - Node *cmplongy= _gvn.transform(new CmpDNode(doublelongy, y)); - // Check if (y isn't long) then go to slow path - - Node *bol2 = _gvn.transform(new BoolNode( cmplongy, BoolTest::ne )); - // Branch either way - IfNode *if2 = create_and_xform_if(complex_path,bol2, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); - Node* ylong_path = _gvn.transform(new IfFalseNode(if2)); - - Node *slow_path = _gvn.transform(new IfTrueNode(if2)); - - // Calculate DPow(abs(x), y)*(1 & (long)y) - // Node for constant 1 - Node *conone = longcon(1); - // 1& (long)y - Node *signnode= _gvn.transform(new AndLNode(conone, longy)); - - // A huge number is always even. Detect a huge number by checking - // if y + 1 == y and set integer to be tested for parity to 0. - // Required for corner case: - // (long)9.223372036854776E18 = max_jlong - // (double)(long)9.223372036854776E18 = 9.223372036854776E18 - // max_jlong is odd but 9.223372036854776E18 is even - Node* yplus1 = _gvn.transform(new AddDNode(y, makecon(TypeD::make(1)))); - Node *cmpyplus1= _gvn.transform(new CmpDNode(yplus1, y)); - Node *bolyplus1 = _gvn.transform(new BoolNode( cmpyplus1, BoolTest::eq )); - Node* correctedsign = NULL; - if (ConditionalMoveLimit != 0) { - correctedsign = _gvn.transform(CMoveNode::make(NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG)); - } else { - IfNode *ifyplus1 = create_and_xform_if(ylong_path,bolyplus1, PROB_FAIR, COUNT_UNKNOWN); - RegionNode *r = new RegionNode(3); - Node *phi = new PhiNode(r, TypeLong::LONG); - r->init_req(1, _gvn.transform(new IfFalseNode(ifyplus1))); - r->init_req(2, _gvn.transform(new IfTrueNode(ifyplus1))); - phi->init_req(1, signnode); - phi->init_req(2, longcon(0)); - correctedsign = _gvn.transform(phi); - ylong_path = _gvn.transform(r); - record_for_igvn(r); - } - - // zero node - Node *conzero = longcon(0); - // Check (1&(long)y)==0? - Node *cmpeq1 = _gvn.transform(new CmpLNode(correctedsign, conzero)); - // Check if (1&(long)y)!=0?, if so the result is negative - Node *bol3 = _gvn.transform(new BoolNode( cmpeq1, BoolTest::ne )); - // abs(x) - Node *absx=_gvn.transform(new AbsDNode(x)); - // abs(x)^y - Node *absxpowy = _gvn.transform(new PowDNode(C, control(), absx, y)); - // -abs(x)^y - Node *negabsxpowy = _gvn.transform(new NegDNode (absxpowy)); - // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y) - Node *signresult = NULL; - if (ConditionalMoveLimit != 0) { - signresult = _gvn.transform(CMoveNode::make(NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); - } else { - IfNode *ifyeven = create_and_xform_if(ylong_path,bol3, PROB_FAIR, COUNT_UNKNOWN); - RegionNode *r = new RegionNode(3); - Node *phi = new PhiNode(r, Type::DOUBLE); - r->init_req(1, _gvn.transform(new IfFalseNode(ifyeven))); - r->init_req(2, _gvn.transform(new IfTrueNode(ifyeven))); - phi->init_req(1, absxpowy); - phi->init_req(2, negabsxpowy); - signresult = _gvn.transform(phi); - ylong_path = _gvn.transform(r); - record_for_igvn(r); - } - // Set complex path fast result - r->init_req(2, ylong_path); - phi->init_req(2, signresult); - - static const jlong nan_bits = CONST64(0x7ff8000000000000); - Node *slow_result = makecon(TypeD::make(*(double*)&nan_bits)); // return NaN - r->init_req(1,slow_path); - phi->init_req(1,slow_result); - - // Post merge - set_control(_gvn.transform(r)); - record_for_igvn(r); - result = _gvn.transform(phi); - } - - result = finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); - - // control from finish_pow_exp is now input to the region node - region_node->set_req(2, control()); - // the result from finish_pow_exp is now input to the phi node - phi_node->init_req(2, result); - set_control(_gvn.transform(region_node)); - record_for_igvn(region_node); - set_result(_gvn.transform(phi_node)); - - C->set_has_split_ifs(true); // Has chance for split-if optimization - return true; -} - //------------------------------runtime_math----------------------------- bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) { assert(call_type == OptoRuntime::Math_DD_D_Type() || call_type == OptoRuntime::Math_D_D_Type(), @@ -2005,8 +1766,10 @@ return StubRoutines::dexp() != NULL ? runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(), "dexp") : runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp), "EXP"); - case vmIntrinsics::_dpow: return Matcher::has_match_rule(Op_PowD) ? inline_pow() : - runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow), "POW"); + case vmIntrinsics::_dpow: + return StubRoutines::dpow() != NULL ? + runtime_math(OptoRuntime::Math_DD_D_Type(), StubRoutines::dpow(), "dpow") : + runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow), "POW"); #undef FN_PTR // These intrinsics are not yet correctly implemented