< prev index next >

src/share/vm/opto/library_call.cpp

Print this page




1528   Node* arg = round_double_node(argument(0));
1529   Node* n = NULL;
1530   switch (id) {
1531   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
1532   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
1533   case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg);  break;
1534   default:  fatal_unexpected_iid(id);  break;
1535   }
1536   set_result(_gvn.transform(n));
1537   return true;
1538 }
1539 
1540 //------------------------------inline_trig----------------------------------
1541 // Inline sin/cos/tan instructions, if possible.  If rounding is required, do
1542 // argument reduction which will turn into a fast/slow diamond.
1543 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
1544   Node* arg = round_double_node(argument(0));
1545   Node* n = NULL;
1546 
1547   switch (id) {
1548   case vmIntrinsics::_dsin:  n = new SinDNode(C, control(), arg);  break;
1549   case vmIntrinsics::_dcos:  n = new CosDNode(C, control(), arg);  break;
1550   case vmIntrinsics::_dtan:  n = new TanDNode(C, control(), arg);  break;
1551   default:  fatal_unexpected_iid(id);  break;
1552   }
1553   n = _gvn.transform(n);
1554 
1555   // Rounding required?  Check for argument reduction!
1556   if (Matcher::strict_fp_requires_explicit_rounding) {
1557     static const double     pi_4 =  0.7853981633974483;
1558     static const double neg_pi_4 = -0.7853981633974483;
1559     // pi/2 in 80-bit extended precision
1560     // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00};
1561     // -pi/2 in 80-bit extended precision
1562     // 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};
1563     // Cutoff value for using this argument reduction technique
1564     //static const double    pi_2_minus_epsilon =  1.564660403643354;
1565     //static const double neg_pi_2_plus_epsilon = -1.564660403643354;
1566 
1567     // Pseudocode for sin:
1568     // if (x <= Math.PI / 4.0) {
1569     //   if (x >= -Math.PI / 4.0) return  fsin(x);


1592     Node* phi = new PhiNode(r, Type::DOUBLE);
1593 
1594     // Flatten arg so we need only 1 test
1595     Node *abs = _gvn.transform(new AbsDNode(arg));
1596     // Node for PI/4 constant
1597     Node *pi4 = makecon(TypeD::make(pi_4));
1598     // Check PI/4 : abs(arg)
1599     Node *cmp = _gvn.transform(new CmpDNode(pi4,abs));
1600     // Check: If PI/4 < abs(arg) then go slow
1601     Node *bol = _gvn.transform(new BoolNode( cmp, BoolTest::lt ));
1602     // Branch either way
1603     IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
1604     set_control(opt_iff(r,iff));
1605 
1606     // Set fast path result
1607     phi->init_req(2, n);
1608 
1609     // Slow path - non-blocking leaf call
1610     Node* call = NULL;
1611     switch (id) {
1612     case vmIntrinsics::_dsin:
1613       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1614                                CAST_FROM_FN_PTR(address, SharedRuntime::dsin),
1615                                "Sin", NULL, arg, top());
1616       break;
1617     case vmIntrinsics::_dcos:
1618       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1619                                CAST_FROM_FN_PTR(address, SharedRuntime::dcos),
1620                                "Cos", NULL, arg, top());
1621       break;
1622     case vmIntrinsics::_dtan:
1623       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1624                                CAST_FROM_FN_PTR(address, SharedRuntime::dtan),
1625                                "Tan", NULL, arg, top());
1626       break;
1627     }
1628     assert(control()->in(0) == call, "");
1629     Node* slow_result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
1630     r->init_req(1, control());
1631     phi->init_req(1, slow_result);
1632 
1633     // Post-merge
1634     set_control(_gvn.transform(r));
1635     record_for_igvn(r);
1636     n = _gvn.transform(phi);
1637 
1638     C->set_has_split_ifs(true); // Has chance for split-if optimization
1639   }
1640   set_result(n);
1641   return true;


1889 
1890   const TypePtr* no_memory_effects = NULL;
1891   Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
1892                                  no_memory_effects,
1893                                  a, top(), b, b ? top() : NULL);
1894   Node* value = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0));
1895 #ifdef ASSERT
1896   Node* value_top = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+1));
1897   assert(value_top == top(), "second value must be top");
1898 #endif
1899 
1900   set_result(value);
1901   return true;
1902 }
1903 
1904 //------------------------------inline_math_native-----------------------------
1905 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) {
1906 #define FN_PTR(f) CAST_FROM_FN_PTR(address, f)
1907   switch (id) {
1908     // These intrinsics are not properly supported on all hardware
1909   case vmIntrinsics::_dcos:   return Matcher::has_match_rule(Op_CosD)   ? inline_trig(id) :
1910     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos),   "COS");
1911   case vmIntrinsics::_dsin:   return Matcher::has_match_rule(Op_SinD)   ? inline_trig(id) :
1912     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin),   "SIN");




1913   case vmIntrinsics::_dtan:   return Matcher::has_match_rule(Op_TanD)   ? inline_trig(id) :
1914     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan),   "TAN");
1915 
1916   case vmIntrinsics::_dlog:
1917     return StubRoutines::dlog() != NULL ?
1918     runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
1919     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog),   "LOG");
1920   case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
1921     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");
1922 
1923     // These intrinsics are supported on all hardware
1924   case vmIntrinsics::_dsqrt:  return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false;
1925   case vmIntrinsics::_dabs:   return Matcher::has_match_rule(Op_AbsD)   ? inline_math(id) : false;
1926 
1927   case vmIntrinsics::_dexp:
1928     return StubRoutines::dexp() != NULL ?
1929       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(),  "dexp") :
1930       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp),  "EXP");
1931   case vmIntrinsics::_dpow:   return Matcher::has_match_rule(Op_PowD)   ? inline_pow()    :
1932     runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow),  "POW");




1528   Node* arg = round_double_node(argument(0));
1529   Node* n = NULL;
1530   switch (id) {
1531   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
1532   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
1533   case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg);  break;
1534   default:  fatal_unexpected_iid(id);  break;
1535   }
1536   set_result(_gvn.transform(n));
1537   return true;
1538 }
1539 
1540 //------------------------------inline_trig----------------------------------
1541 // Inline sin/cos/tan instructions, if possible.  If rounding is required, do
1542 // argument reduction which will turn into a fast/slow diamond.
1543 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
1544   Node* arg = round_double_node(argument(0));
1545   Node* n = NULL;
1546 
1547   switch (id) {


1548   case vmIntrinsics::_dtan:  n = new TanDNode(C, control(), arg);  break;
1549   default:  fatal_unexpected_iid(id);  break;
1550   }
1551   n = _gvn.transform(n);
1552 
1553   // Rounding required?  Check for argument reduction!
1554   if (Matcher::strict_fp_requires_explicit_rounding) {
1555     static const double     pi_4 =  0.7853981633974483;
1556     static const double neg_pi_4 = -0.7853981633974483;
1557     // pi/2 in 80-bit extended precision
1558     // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00};
1559     // -pi/2 in 80-bit extended precision
1560     // 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};
1561     // Cutoff value for using this argument reduction technique
1562     //static const double    pi_2_minus_epsilon =  1.564660403643354;
1563     //static const double neg_pi_2_plus_epsilon = -1.564660403643354;
1564 
1565     // Pseudocode for sin:
1566     // if (x <= Math.PI / 4.0) {
1567     //   if (x >= -Math.PI / 4.0) return  fsin(x);


1590     Node* phi = new PhiNode(r, Type::DOUBLE);
1591 
1592     // Flatten arg so we need only 1 test
1593     Node *abs = _gvn.transform(new AbsDNode(arg));
1594     // Node for PI/4 constant
1595     Node *pi4 = makecon(TypeD::make(pi_4));
1596     // Check PI/4 : abs(arg)
1597     Node *cmp = _gvn.transform(new CmpDNode(pi4,abs));
1598     // Check: If PI/4 < abs(arg) then go slow
1599     Node *bol = _gvn.transform(new BoolNode( cmp, BoolTest::lt ));
1600     // Branch either way
1601     IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
1602     set_control(opt_iff(r,iff));
1603 
1604     // Set fast path result
1605     phi->init_req(2, n);
1606 
1607     // Slow path - non-blocking leaf call
1608     Node* call = NULL;
1609     switch (id) {










1610     case vmIntrinsics::_dtan:
1611       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1612                                CAST_FROM_FN_PTR(address, SharedRuntime::dtan),
1613                                "Tan", NULL, arg, top());
1614       break;
1615     }
1616     assert(control()->in(0) == call, "");
1617     Node* slow_result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
1618     r->init_req(1, control());
1619     phi->init_req(1, slow_result);
1620 
1621     // Post-merge
1622     set_control(_gvn.transform(r));
1623     record_for_igvn(r);
1624     n = _gvn.transform(phi);
1625 
1626     C->set_has_split_ifs(true); // Has chance for split-if optimization
1627   }
1628   set_result(n);
1629   return true;


1877 
1878   const TypePtr* no_memory_effects = NULL;
1879   Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
1880                                  no_memory_effects,
1881                                  a, top(), b, b ? top() : NULL);
1882   Node* value = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0));
1883 #ifdef ASSERT
1884   Node* value_top = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+1));
1885   assert(value_top == top(), "second value must be top");
1886 #endif
1887 
1888   set_result(value);
1889   return true;
1890 }
1891 
1892 //------------------------------inline_math_native-----------------------------
1893 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) {
1894 #define FN_PTR(f) CAST_FROM_FN_PTR(address, f)
1895   switch (id) {
1896     // These intrinsics are not properly supported on all hardware
1897   case vmIntrinsics::_dsin:
1898     return StubRoutines::dsin() != NULL ?
1899       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dsin(), "dsin") :
1900       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin),   "SIN");
1901   case vmIntrinsics::_dcos:
1902     return StubRoutines::dcos() != NULL ?
1903       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dcos(), "dcos") :
1904       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos),   "COS");
1905   case vmIntrinsics::_dtan:   return Matcher::has_match_rule(Op_TanD)   ? inline_trig(id) :
1906     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan),   "TAN");
1907 
1908   case vmIntrinsics::_dlog:
1909     return StubRoutines::dlog() != NULL ?
1910       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
1911       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog),   "LOG");
1912   case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
1913     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");
1914 
1915     // These intrinsics are supported on all hardware
1916   case vmIntrinsics::_dsqrt:  return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false;
1917   case vmIntrinsics::_dabs:   return Matcher::has_match_rule(Op_AbsD)   ? inline_math(id) : false;
1918 
1919   case vmIntrinsics::_dexp:
1920     return StubRoutines::dexp() != NULL ?
1921       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(),  "dexp") :
1922       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp),  "EXP");
1923   case vmIntrinsics::_dpow:   return Matcher::has_match_rule(Op_PowD)   ? inline_pow()    :
1924     runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow),  "POW");


< prev index next >