1659 1660 //--------------------------round_double_node-------------------------------- 1661 // Round a double node if necessary. 1662 Node* LibraryCallKit::round_double_node(Node* n) { 1663 if (Matcher::strict_fp_requires_explicit_rounding && UseSSE <= 1) 1664 n = _gvn.transform(new RoundDoubleNode(0, n)); 1665 return n; 1666 } 1667 1668 //------------------------------inline_math----------------------------------- 1669 // public static double Math.abs(double) 1670 // public static double Math.sqrt(double) 1671 // public static double Math.log(double) 1672 // public static double Math.log10(double) 1673 bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { 1674 Node* arg = round_double_node(argument(0)); 1675 Node* n = NULL; 1676 switch (id) { 1677 case vmIntrinsics::_dabs: n = new AbsDNode( arg); break; 1678 case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break; 1679 case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg); break; 1680 default: fatal_unexpected_iid(id); break; 1681 } 1682 set_result(_gvn.transform(n)); 1683 return true; 1684 } 1685 1686 //------------------------------inline_trig---------------------------------- 1687 // Inline sin/cos/tan instructions, if possible. If rounding is required, do 1688 // argument reduction which will turn into a fast/slow diamond. 1689 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { 1690 Node* arg = round_double_node(argument(0)); 1691 Node* n = NULL; 1692 1693 switch (id) { 1694 case vmIntrinsics::_dtan: n = new TanDNode(C, control(), arg); break; 1695 default: fatal_unexpected_iid(id); break; 1696 } 1697 n = _gvn.transform(n); 1698 1699 // Rounding required? Check for argument reduction! 1700 if (Matcher::strict_fp_requires_explicit_rounding) { 1701 static const double pi_4 = 0.7853981633974483; 1702 static const double neg_pi_4 = -0.7853981633974483; 1703 // pi/2 in 80-bit extended precision 1704 // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00}; 1705 // -pi/2 in 80-bit extended precision 1706 // static const unsigned char neg_pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0xbf,0x00,0x00,0x00,0x00,0x00,0x00}; 1707 // Cutoff value for using this argument reduction technique 1708 //static const double pi_2_minus_epsilon = 1.564660403643354; 1709 //static const double neg_pi_2_plus_epsilon = -1.564660403643354; 1710 1711 // Pseudocode for sin: 1712 // if (x <= Math.PI / 4.0) { 1713 // if (x >= -Math.PI / 4.0) return fsin(x); 1714 // if (x >= -Math.PI / 2.0) return -fcos(x + Math.PI / 2.0); 1715 // } else { 1716 // if (x <= Math.PI / 2.0) return fcos(x - Math.PI / 2.0); 1794 assert(value_top == top(), "second value must be top"); 1795 #endif 1796 1797 set_result(value); 1798 return true; 1799 } 1800 1801 //------------------------------inline_math_native----------------------------- 1802 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { 1803 #define FN_PTR(f) CAST_FROM_FN_PTR(address, f) 1804 switch (id) { 1805 // These intrinsics are not properly supported on all hardware 1806 case vmIntrinsics::_dsin: 1807 return StubRoutines::dsin() != NULL ? 1808 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dsin(), "dsin") : 1809 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin), "SIN"); 1810 case vmIntrinsics::_dcos: 1811 return StubRoutines::dcos() != NULL ? 1812 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dcos(), "dcos") : 1813 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos), "COS"); 1814 case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) : 1815 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN"); 1816 1817 case vmIntrinsics::_dlog: 1818 return StubRoutines::dlog() != NULL ? 1819 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") : 1820 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG"); 1821 case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) : 1822 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); 1823 1824 // These intrinsics are supported on all hardware 1825 case vmIntrinsics::_dsqrt: return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false; 1826 case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_math(id) : false; 1827 1828 case vmIntrinsics::_dexp: 1829 return StubRoutines::dexp() != NULL ? 1830 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(), "dexp") : 1831 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp), "EXP"); 1832 case vmIntrinsics::_dpow: 1833 return StubRoutines::dpow() != NULL ? 1834 runtime_math(OptoRuntime::Math_DD_D_Type(), StubRoutines::dpow(), "dpow") : 1835 runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow), "POW"); 1836 #undef FN_PTR 1837 1838 // These intrinsics are not yet correctly implemented 1839 case vmIntrinsics::_datan2: 1840 return false; 1841 | 1659 1660 //--------------------------round_double_node-------------------------------- 1661 // Round a double node if necessary. 1662 Node* LibraryCallKit::round_double_node(Node* n) { 1663 if (Matcher::strict_fp_requires_explicit_rounding && UseSSE <= 1) 1664 n = _gvn.transform(new RoundDoubleNode(0, n)); 1665 return n; 1666 } 1667 1668 //------------------------------inline_math----------------------------------- 1669 // public static double Math.abs(double) 1670 // public static double Math.sqrt(double) 1671 // public static double Math.log(double) 1672 // public static double Math.log10(double) 1673 bool LibraryCallKit::inline_math(vmIntrinsics::ID id) { 1674 Node* arg = round_double_node(argument(0)); 1675 Node* n = NULL; 1676 switch (id) { 1677 case vmIntrinsics::_dabs: n = new AbsDNode( arg); break; 1678 case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break; 1679 default: fatal_unexpected_iid(id); break; 1680 } 1681 set_result(_gvn.transform(n)); 1682 return true; 1683 } 1684 1685 //------------------------------inline_trig---------------------------------- 1686 // Inline sin/cos/tan instructions, if possible. If rounding is required, do 1687 // argument reduction which will turn into a fast/slow diamond. 1688 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) { 1689 Node* arg = round_double_node(argument(0)); 1690 Node* n = NULL; 1691 1692 n = _gvn.transform(n); 1693 1694 // Rounding required? Check for argument reduction! 1695 if (Matcher::strict_fp_requires_explicit_rounding) { 1696 static const double pi_4 = 0.7853981633974483; 1697 static const double neg_pi_4 = -0.7853981633974483; 1698 // pi/2 in 80-bit extended precision 1699 // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00}; 1700 // -pi/2 in 80-bit extended precision 1701 // static const unsigned char neg_pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0xbf,0x00,0x00,0x00,0x00,0x00,0x00}; 1702 // Cutoff value for using this argument reduction technique 1703 //static const double pi_2_minus_epsilon = 1.564660403643354; 1704 //static const double neg_pi_2_plus_epsilon = -1.564660403643354; 1705 1706 // Pseudocode for sin: 1707 // if (x <= Math.PI / 4.0) { 1708 // if (x >= -Math.PI / 4.0) return fsin(x); 1709 // if (x >= -Math.PI / 2.0) return -fcos(x + Math.PI / 2.0); 1710 // } else { 1711 // if (x <= Math.PI / 2.0) return fcos(x - Math.PI / 2.0); 1789 assert(value_top == top(), "second value must be top"); 1790 #endif 1791 1792 set_result(value); 1793 return true; 1794 } 1795 1796 //------------------------------inline_math_native----------------------------- 1797 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) { 1798 #define FN_PTR(f) CAST_FROM_FN_PTR(address, f) 1799 switch (id) { 1800 // These intrinsics are not properly supported on all hardware 1801 case vmIntrinsics::_dsin: 1802 return StubRoutines::dsin() != NULL ? 1803 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dsin(), "dsin") : 1804 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin), "SIN"); 1805 case vmIntrinsics::_dcos: 1806 return StubRoutines::dcos() != NULL ? 1807 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dcos(), "dcos") : 1808 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos), "COS"); 1809 case vmIntrinsics::_dtan: 1810 return StubRoutines::dtan() != NULL ? 1811 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dtan(), "dtan") : 1812 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN"); 1813 case vmIntrinsics::_dlog: 1814 return StubRoutines::dlog() != NULL ? 1815 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") : 1816 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG"); 1817 case vmIntrinsics::_dlog10: 1818 return StubRoutines::dlog10() != NULL ? 1819 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog10(), "dlog10") : 1820 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10"); 1821 1822 // These intrinsics are supported on all hardware 1823 case vmIntrinsics::_dsqrt: return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false; 1824 case vmIntrinsics::_dabs: return Matcher::has_match_rule(Op_AbsD) ? inline_math(id) : false; 1825 1826 case vmIntrinsics::_dexp: 1827 return StubRoutines::dexp() != NULL ? 1828 runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(), "dexp") : 1829 runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp), "EXP"); 1830 case vmIntrinsics::_dpow: 1831 return StubRoutines::dpow() != NULL ? 1832 runtime_math(OptoRuntime::Math_DD_D_Type(), StubRoutines::dpow(), "dpow") : 1833 runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow), "POW"); 1834 #undef FN_PTR 1835 1836 // These intrinsics are not yet correctly implemented 1837 case vmIntrinsics::_datan2: 1838 return false; 1839 |