Mercurial > hg > truffle
comparison src/share/vm/opto/library_call.cpp @ 6205:d50605d9417e
7177917: Failed test java/lang/Math/PowTests.java
Summary: When c2 intrinsifies pow/exp, it should never inline the java implementations.
Reviewed-by: kvn
author | roland |
---|---|
date | Mon, 02 Jul 2012 09:58:06 +0200 |
parents | eeb819cf36e5 |
children | 1d7922586cf6 |
comparison
equal
deleted
inserted
replaced
6195:bcffa4c5eef6 | 6205:d50605d9417e |
---|---|
158 bool inline_math_native(vmIntrinsics::ID id); | 158 bool inline_math_native(vmIntrinsics::ID id); |
159 bool inline_trig(vmIntrinsics::ID id); | 159 bool inline_trig(vmIntrinsics::ID id); |
160 bool inline_trans(vmIntrinsics::ID id); | 160 bool inline_trans(vmIntrinsics::ID id); |
161 bool inline_abs(vmIntrinsics::ID id); | 161 bool inline_abs(vmIntrinsics::ID id); |
162 bool inline_sqrt(vmIntrinsics::ID id); | 162 bool inline_sqrt(vmIntrinsics::ID id); |
163 void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName); | |
163 bool inline_pow(vmIntrinsics::ID id); | 164 bool inline_pow(vmIntrinsics::ID id); |
164 bool inline_exp(vmIntrinsics::ID id); | 165 bool inline_exp(vmIntrinsics::ID id); |
165 bool inline_min_max(vmIntrinsics::ID id); | 166 bool inline_min_max(vmIntrinsics::ID id); |
166 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); | 167 Node* generate_min_max(vmIntrinsics::ID id, Node* x, Node* y); |
167 // This returns Type::AnyPtr, RawPtr, or OopPtr. | 168 // This returns Type::AnyPtr, RawPtr, or OopPtr. |
1533 _sp += arg_size(); // restore stack pointer | 1534 _sp += arg_size(); // restore stack pointer |
1534 push_pair(_gvn.transform(new (C, 2) AbsDNode(pop_math_arg()))); | 1535 push_pair(_gvn.transform(new (C, 2) AbsDNode(pop_math_arg()))); |
1535 return true; | 1536 return true; |
1536 } | 1537 } |
1537 | 1538 |
1539 void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName) { | |
1540 //------------------- | |
1541 //result=(result.isNaN())? funcAddr():result; | |
1542 // Check: If isNaN() by checking result!=result? then either trap | |
1543 // or go to runtime | |
1544 Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result)); | |
1545 // Build the boolean node | |
1546 Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) ); | |
1547 | |
1548 if (!too_many_traps(Deoptimization::Reason_intrinsic)) { | |
1549 { | |
1550 BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); | |
1551 // End the current control-flow path | |
1552 push_pair(x); | |
1553 if (y != NULL) { | |
1554 push_pair(y); | |
1555 } | |
1556 // The pow or exp intrinsic returned a NaN, which requires a call | |
1557 // to the runtime. Recompile with the runtime call. | |
1558 uncommon_trap(Deoptimization::Reason_intrinsic, | |
1559 Deoptimization::Action_make_not_entrant); | |
1560 } | |
1561 push_pair(result); | |
1562 } else { | |
1563 // If this inlining ever returned NaN in the past, we compile a call | |
1564 // to the runtime to properly handle corner cases | |
1565 | |
1566 IfNode* iff = create_and_xform_if(control(), bolisnum, PROB_STATIC_FREQUENT, COUNT_UNKNOWN); | |
1567 Node* if_slow = _gvn.transform( new (C, 1) IfFalseNode(iff) ); | |
1568 Node* if_fast = _gvn.transform( new (C, 1) IfTrueNode(iff) ); | |
1569 | |
1570 if (!if_slow->is_top()) { | |
1571 RegionNode* result_region = new(C, 3) RegionNode(3); | |
1572 PhiNode* result_val = new (C, 3) PhiNode(result_region, Type::DOUBLE); | |
1573 | |
1574 result_region->init_req(1, if_fast); | |
1575 result_val->init_req(1, result); | |
1576 | |
1577 set_control(if_slow); | |
1578 | |
1579 const TypePtr* no_memory_effects = NULL; | |
1580 Node* rt = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName, | |
1581 no_memory_effects, | |
1582 x, top(), y, y ? top() : NULL); | |
1583 Node* value = _gvn.transform(new (C, 1) ProjNode(rt, TypeFunc::Parms+0)); | |
1584 #ifdef ASSERT | |
1585 Node* value_top = _gvn.transform(new (C, 1) ProjNode(rt, TypeFunc::Parms+1)); | |
1586 assert(value_top == top(), "second value must be top"); | |
1587 #endif | |
1588 | |
1589 result_region->init_req(2, control()); | |
1590 result_val->init_req(2, value); | |
1591 push_result(result_region, result_val); | |
1592 } else { | |
1593 push_pair(result); | |
1594 } | |
1595 } | |
1596 } | |
1597 | |
1538 //------------------------------inline_exp------------------------------------- | 1598 //------------------------------inline_exp------------------------------------- |
1539 // Inline exp instructions, if possible. The Intel hardware only misses | 1599 // Inline exp instructions, if possible. The Intel hardware only misses |
1540 // really odd corner cases (+/- Infinity). Just uncommon-trap them. | 1600 // really odd corner cases (+/- Infinity). Just uncommon-trap them. |
1541 bool LibraryCallKit::inline_exp(vmIntrinsics::ID id) { | 1601 bool LibraryCallKit::inline_exp(vmIntrinsics::ID id) { |
1542 assert(id == vmIntrinsics::_dexp, "Not exp"); | 1602 assert(id == vmIntrinsics::_dexp, "Not exp"); |
1543 | 1603 |
1544 // If this inlining ever returned NaN in the past, we do not intrinsify it | |
1545 // every again. NaN results requires StrictMath.exp handling. | |
1546 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
1547 | |
1548 _sp += arg_size(); // restore stack pointer | 1604 _sp += arg_size(); // restore stack pointer |
1549 Node *x = pop_math_arg(); | 1605 Node *x = pop_math_arg(); |
1550 Node *result = _gvn.transform(new (C, 2) ExpDNode(0,x)); | 1606 Node *result = _gvn.transform(new (C, 2) ExpDNode(0,x)); |
1551 | 1607 |
1552 //------------------- | 1608 finish_pow_exp(result, x, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP"); |
1553 //result=(result.isNaN())? StrictMath::exp():result; | |
1554 // Check: If isNaN() by checking result!=result? then go to Strict Math | |
1555 Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result)); | |
1556 // Build the boolean node | |
1557 Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) ); | |
1558 | |
1559 { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); | |
1560 // End the current control-flow path | |
1561 push_pair(x); | |
1562 // Math.exp intrinsic returned a NaN, which requires StrictMath.exp | |
1563 // to handle. Recompile without intrinsifying Math.exp | |
1564 uncommon_trap(Deoptimization::Reason_intrinsic, | |
1565 Deoptimization::Action_make_not_entrant); | |
1566 } | |
1567 | 1609 |
1568 C->set_has_split_ifs(true); // Has chance for split-if optimization | 1610 C->set_has_split_ifs(true); // Has chance for split-if optimization |
1569 | |
1570 push_pair(result); | |
1571 | 1611 |
1572 return true; | 1612 return true; |
1573 } | 1613 } |
1574 | 1614 |
1575 //------------------------------inline_pow------------------------------------- | 1615 //------------------------------inline_pow------------------------------------- |
1576 // Inline power instructions, if possible. | 1616 // Inline power instructions, if possible. |
1577 bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) { | 1617 bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) { |
1578 assert(id == vmIntrinsics::_dpow, "Not pow"); | 1618 assert(id == vmIntrinsics::_dpow, "Not pow"); |
1579 | 1619 |
1580 // If this inlining ever returned NaN in the past, we do not intrinsify it | |
1581 // every again. NaN results requires StrictMath.pow handling. | |
1582 if (too_many_traps(Deoptimization::Reason_intrinsic)) return false; | |
1583 | |
1584 // Do not intrinsify on older platforms which lack cmove. | |
1585 if (ConditionalMoveLimit == 0) return false; | |
1586 | |
1587 // Pseudocode for pow | 1620 // Pseudocode for pow |
1588 // if (x <= 0.0) { | 1621 // if (x <= 0.0) { |
1589 // if ((double)((int)y)==y) { // if y is int | 1622 // long longy = (long)y; |
1590 // result = ((1&(int)y)==0)?-DPow(abs(x), y):DPow(abs(x), y) | 1623 // if ((double)longy == y) { // if y is long |
1624 // if (y + 1 == y) longy = 0; // huge number: even | |
1625 // result = ((1&longy) == 0)?-DPow(abs(x), y):DPow(abs(x), y); | |
1591 // } else { | 1626 // } else { |
1592 // result = NaN; | 1627 // result = NaN; |
1593 // } | 1628 // } |
1594 // } else { | 1629 // } else { |
1595 // result = DPow(x,y); | 1630 // result = DPow(x,y); |
1596 // } | 1631 // } |
1597 // if (result != result)? { | 1632 // if (result != result)? { |
1598 // uncommon_trap(); | 1633 // result = uncommon_trap() or runtime_call(); |
1599 // } | 1634 // } |
1600 // return result; | 1635 // return result; |
1601 | 1636 |
1602 _sp += arg_size(); // restore stack pointer | 1637 _sp += arg_size(); // restore stack pointer |
1603 Node* y = pop_math_arg(); | 1638 Node* y = pop_math_arg(); |
1604 Node* x = pop_math_arg(); | 1639 Node* x = pop_math_arg(); |
1605 | 1640 |
1606 Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, x, y) ); | 1641 Node* result = NULL; |
1607 | 1642 |
1608 // Short form: if not top-level (i.e., Math.pow but inlining Math.pow | 1643 if (!too_many_traps(Deoptimization::Reason_intrinsic)) { |
1609 // inside of something) then skip the fancy tests and just check for | 1644 // Short form: skip the fancy tests and just check for NaN result. |
1610 // NaN result. | 1645 result = _gvn.transform( new (C, 3) PowDNode(0, x, y) ); |
1611 Node *result = NULL; | |
1612 if( jvms()->depth() >= 1 ) { | |
1613 result = fast_result; | |
1614 } else { | 1646 } else { |
1647 // If this inlining ever returned NaN in the past, include all | |
1648 // checks + call to the runtime. | |
1615 | 1649 |
1616 // Set the merge point for If node with condition of (x <= 0.0) | 1650 // Set the merge point for If node with condition of (x <= 0.0) |
1617 // There are four possible paths to region node and phi node | 1651 // There are four possible paths to region node and phi node |
1618 RegionNode *r = new (C, 4) RegionNode(4); | 1652 RegionNode *r = new (C, 4) RegionNode(4); |
1619 Node *phi = new (C, 4) PhiNode(r, Type::DOUBLE); | 1653 Node *phi = new (C, 4) PhiNode(r, Type::DOUBLE); |
1625 Node *cmp = _gvn.transform(new (C, 3) CmpDNode(x, zeronode)); | 1659 Node *cmp = _gvn.transform(new (C, 3) CmpDNode(x, zeronode)); |
1626 // Check: If (x<=0) then go complex path | 1660 // Check: If (x<=0) then go complex path |
1627 Node *bol1 = _gvn.transform( new (C, 2) BoolNode( cmp, BoolTest::le ) ); | 1661 Node *bol1 = _gvn.transform( new (C, 2) BoolNode( cmp, BoolTest::le ) ); |
1628 // Branch either way | 1662 // Branch either way |
1629 IfNode *if1 = create_and_xform_if(control(),bol1, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); | 1663 IfNode *if1 = create_and_xform_if(control(),bol1, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); |
1630 Node *opt_test = _gvn.transform(if1); | |
1631 //assert( opt_test->is_If(), "Expect an IfNode"); | |
1632 IfNode *opt_if1 = (IfNode*)opt_test; | |
1633 // Fast path taken; set region slot 3 | 1664 // Fast path taken; set region slot 3 |
1634 Node *fast_taken = _gvn.transform( new (C, 1) IfFalseNode(opt_if1) ); | 1665 Node *fast_taken = _gvn.transform( new (C, 1) IfFalseNode(if1) ); |
1635 r->init_req(3,fast_taken); // Capture fast-control | 1666 r->init_req(3,fast_taken); // Capture fast-control |
1636 | 1667 |
1637 // Fast path not-taken, i.e. slow path | 1668 // Fast path not-taken, i.e. slow path |
1638 Node *complex_path = _gvn.transform( new (C, 1) IfTrueNode(opt_if1) ); | 1669 Node *complex_path = _gvn.transform( new (C, 1) IfTrueNode(if1) ); |
1639 | 1670 |
1640 // Set fast path result | 1671 // Set fast path result |
1641 Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, y, x) ); | 1672 Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, x, y) ); |
1642 phi->init_req(3, fast_result); | 1673 phi->init_req(3, fast_result); |
1643 | 1674 |
1644 // Complex path | 1675 // Complex path |
1645 // Build the second if node (if y is int) | 1676 // Build the second if node (if y is long) |
1646 // Node for (int)y | 1677 // Node for (long)y |
1647 Node *inty = _gvn.transform( new (C, 2) ConvD2INode(y)); | 1678 Node *longy = _gvn.transform( new (C, 2) ConvD2LNode(y)); |
1648 // Node for (double)((int) y) | 1679 // Node for (double)((long) y) |
1649 Node *doubleinty= _gvn.transform( new (C, 2) ConvI2DNode(inty)); | 1680 Node *doublelongy= _gvn.transform( new (C, 2) ConvL2DNode(longy)); |
1650 // Check (double)((int) y) : y | 1681 // Check (double)((long) y) : y |
1651 Node *cmpinty= _gvn.transform(new (C, 3) CmpDNode(doubleinty, y)); | 1682 Node *cmplongy= _gvn.transform(new (C, 3) CmpDNode(doublelongy, y)); |
1652 // Check if (y isn't int) then go to slow path | 1683 // Check if (y isn't long) then go to slow path |
1653 | 1684 |
1654 Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmpinty, BoolTest::ne ) ); | 1685 Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmplongy, BoolTest::ne ) ); |
1655 // Branch either way | 1686 // Branch either way |
1656 IfNode *if2 = create_and_xform_if(complex_path,bol2, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); | 1687 IfNode *if2 = create_and_xform_if(complex_path,bol2, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN); |
1657 Node *slow_path = opt_iff(r,if2); // Set region path 2 | 1688 Node* ylong_path = _gvn.transform( new (C, 1) IfFalseNode(if2)); |
1658 | 1689 |
1659 // Calculate DPow(abs(x), y)*(1 & (int)y) | 1690 Node *slow_path = _gvn.transform( new (C, 1) IfTrueNode(if2) ); |
1691 | |
1692 // Calculate DPow(abs(x), y)*(1 & (long)y) | |
1660 // Node for constant 1 | 1693 // Node for constant 1 |
1661 Node *conone = intcon(1); | 1694 Node *conone = longcon(1); |
1662 // 1& (int)y | 1695 // 1& (long)y |
1663 Node *signnode= _gvn.transform( new (C, 3) AndINode(conone, inty) ); | 1696 Node *signnode= _gvn.transform( new (C, 3) AndLNode(conone, longy) ); |
1697 | |
1698 // A huge number is always even. Detect a huge number by checking | |
1699 // if y + 1 == y and set integer to be tested for parity to 0. | |
1700 // Required for corner case: | |
1701 // (long)9.223372036854776E18 = max_jlong | |
1702 // (double)(long)9.223372036854776E18 = 9.223372036854776E18 | |
1703 // max_jlong is odd but 9.223372036854776E18 is even | |
1704 Node* yplus1 = _gvn.transform( new (C, 3) AddDNode(y, makecon(TypeD::make(1)))); | |
1705 Node *cmpyplus1= _gvn.transform(new (C, 3) CmpDNode(yplus1, y)); | |
1706 Node *bolyplus1 = _gvn.transform( new (C, 2) BoolNode( cmpyplus1, BoolTest::eq ) ); | |
1707 Node* correctedsign = NULL; | |
1708 if (ConditionalMoveLimit != 0) { | |
1709 correctedsign = _gvn.transform( CMoveNode::make(C, NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG)); | |
1710 } else { | |
1711 IfNode *ifyplus1 = create_and_xform_if(ylong_path,bolyplus1, PROB_FAIR, COUNT_UNKNOWN); | |
1712 RegionNode *r = new (C, 3) RegionNode(3); | |
1713 Node *phi = new (C, 3) PhiNode(r, TypeLong::LONG); | |
1714 r->init_req(1, _gvn.transform( new (C, 1) IfFalseNode(ifyplus1))); | |
1715 r->init_req(2, _gvn.transform( new (C, 1) IfTrueNode(ifyplus1))); | |
1716 phi->init_req(1, signnode); | |
1717 phi->init_req(2, longcon(0)); | |
1718 correctedsign = _gvn.transform(phi); | |
1719 ylong_path = _gvn.transform(r); | |
1720 record_for_igvn(r); | |
1721 } | |
1722 | |
1664 // zero node | 1723 // zero node |
1665 Node *conzero = intcon(0); | 1724 Node *conzero = longcon(0); |
1666 // Check (1&(int)y)==0? | 1725 // Check (1&(long)y)==0? |
1667 Node *cmpeq1 = _gvn.transform(new (C, 3) CmpINode(signnode, conzero)); | 1726 Node *cmpeq1 = _gvn.transform(new (C, 3) CmpLNode(correctedsign, conzero)); |
1668 // Check if (1&(int)y)!=0?, if so the result is negative | 1727 // Check if (1&(long)y)!=0?, if so the result is negative |
1669 Node *bol3 = _gvn.transform( new (C, 2) BoolNode( cmpeq1, BoolTest::ne ) ); | 1728 Node *bol3 = _gvn.transform( new (C, 2) BoolNode( cmpeq1, BoolTest::ne ) ); |
1670 // abs(x) | 1729 // abs(x) |
1671 Node *absx=_gvn.transform( new (C, 2) AbsDNode(x)); | 1730 Node *absx=_gvn.transform( new (C, 2) AbsDNode(x)); |
1672 // abs(x)^y | 1731 // abs(x)^y |
1673 Node *absxpowy = _gvn.transform( new (C, 3) PowDNode(0, y, absx) ); | 1732 Node *absxpowy = _gvn.transform( new (C, 3) PowDNode(0, absx, y) ); |
1674 // -abs(x)^y | 1733 // -abs(x)^y |
1675 Node *negabsxpowy = _gvn.transform(new (C, 2) NegDNode (absxpowy)); | 1734 Node *negabsxpowy = _gvn.transform(new (C, 2) NegDNode (absxpowy)); |
1676 // (1&(int)y)==1?-DPow(abs(x), y):DPow(abs(x), y) | 1735 // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y) |
1677 Node *signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); | 1736 Node *signresult = NULL; |
1737 if (ConditionalMoveLimit != 0) { | |
1738 signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE)); | |
1739 } else { | |
1740 IfNode *ifyeven = create_and_xform_if(ylong_path,bol3, PROB_FAIR, COUNT_UNKNOWN); | |
1741 RegionNode *r = new (C, 3) RegionNode(3); | |
1742 Node *phi = new (C, 3) PhiNode(r, Type::DOUBLE); | |
1743 r->init_req(1, _gvn.transform( new (C, 1) IfFalseNode(ifyeven))); | |
1744 r->init_req(2, _gvn.transform( new (C, 1) IfTrueNode(ifyeven))); | |
1745 phi->init_req(1, absxpowy); | |
1746 phi->init_req(2, negabsxpowy); | |
1747 signresult = _gvn.transform(phi); | |
1748 ylong_path = _gvn.transform(r); | |
1749 record_for_igvn(r); | |
1750 } | |
1678 // Set complex path fast result | 1751 // Set complex path fast result |
1752 r->init_req(2, ylong_path); | |
1679 phi->init_req(2, signresult); | 1753 phi->init_req(2, signresult); |
1680 | 1754 |
1681 static const jlong nan_bits = CONST64(0x7ff8000000000000); | 1755 static const jlong nan_bits = CONST64(0x7ff8000000000000); |
1682 Node *slow_result = makecon(TypeD::make(*(double*)&nan_bits)); // return NaN | 1756 Node *slow_result = makecon(TypeD::make(*(double*)&nan_bits)); // return NaN |
1683 r->init_req(1,slow_path); | 1757 r->init_req(1,slow_path); |
1687 set_control(_gvn.transform(r)); | 1761 set_control(_gvn.transform(r)); |
1688 record_for_igvn(r); | 1762 record_for_igvn(r); |
1689 result=_gvn.transform(phi); | 1763 result=_gvn.transform(phi); |
1690 } | 1764 } |
1691 | 1765 |
1692 //------------------- | 1766 finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); |
1693 //result=(result.isNaN())? uncommon_trap():result; | |
1694 // Check: If isNaN() by checking result!=result? then go to Strict Math | |
1695 Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result)); | |
1696 // Build the boolean node | |
1697 Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) ); | |
1698 | |
1699 { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT); | |
1700 // End the current control-flow path | |
1701 push_pair(x); | |
1702 push_pair(y); | |
1703 // Math.pow intrinsic returned a NaN, which requires StrictMath.pow | |
1704 // to handle. Recompile without intrinsifying Math.pow. | |
1705 uncommon_trap(Deoptimization::Reason_intrinsic, | |
1706 Deoptimization::Action_make_not_entrant); | |
1707 } | |
1708 | 1767 |
1709 C->set_has_split_ifs(true); // Has chance for split-if optimization | 1768 C->set_has_split_ifs(true); // Has chance for split-if optimization |
1710 | |
1711 push_pair(result); | |
1712 | 1769 |
1713 return true; | 1770 return true; |
1714 } | 1771 } |
1715 | 1772 |
1716 //------------------------------inline_trans------------------------------------- | 1773 //------------------------------inline_trans------------------------------------- |