< prev index next >

src/share/vm/opto/library_call.cpp

Print this page




1596   Node* arg = round_double_node(argument(0));
1597   Node* n = NULL;
1598   switch (id) {
1599   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
1600   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
1601   case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg);  break;
1602   default:  fatal_unexpected_iid(id);  break;
1603   }
1604   set_result(_gvn.transform(n));
1605   return true;
1606 }
1607 
1608 //------------------------------inline_trig----------------------------------
1609 // Inline sin/cos/tan instructions, if possible.  If rounding is required, do
1610 // argument reduction which will turn into a fast/slow diamond.
1611 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
1612   Node* arg = round_double_node(argument(0));
1613   Node* n = NULL;
1614 
1615   switch (id) {
1616   case vmIntrinsics::_dsin:  n = new SinDNode(C, control(), arg);  break;
1617   case vmIntrinsics::_dcos:  n = new CosDNode(C, control(), arg);  break;
1618   case vmIntrinsics::_dtan:  n = new TanDNode(C, control(), arg);  break;
1619   default:  fatal_unexpected_iid(id);  break;
1620   }
1621   n = _gvn.transform(n);
1622 
1623   // Rounding required?  Check for argument reduction!
1624   if (Matcher::strict_fp_requires_explicit_rounding) {
1625     static const double     pi_4 =  0.7853981633974483;
1626     static const double neg_pi_4 = -0.7853981633974483;
1627     // pi/2 in 80-bit extended precision
1628     // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00};
1629     // -pi/2 in 80-bit extended precision
1630     // 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};
1631     // Cutoff value for using this argument reduction technique
1632     //static const double    pi_2_minus_epsilon =  1.564660403643354;
1633     //static const double neg_pi_2_plus_epsilon = -1.564660403643354;
1634 
1635     // Pseudocode for sin:
1636     // if (x <= Math.PI / 4.0) {
1637     //   if (x >= -Math.PI / 4.0) return  fsin(x);


1660     Node* phi = new PhiNode(r, Type::DOUBLE);
1661 
1662     // Flatten arg so we need only 1 test
1663     Node *abs = _gvn.transform(new AbsDNode(arg));
1664     // Node for PI/4 constant
1665     Node *pi4 = makecon(TypeD::make(pi_4));
1666     // Check PI/4 : abs(arg)
1667     Node *cmp = _gvn.transform(new CmpDNode(pi4,abs));
1668     // Check: If PI/4 < abs(arg) then go slow
1669     Node *bol = _gvn.transform(new BoolNode( cmp, BoolTest::lt ));
1670     // Branch either way
1671     IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
1672     set_control(opt_iff(r,iff));
1673 
1674     // Set fast path result
1675     phi->init_req(2, n);
1676 
1677     // Slow path - non-blocking leaf call
1678     Node* call = NULL;
1679     switch (id) {
1680     case vmIntrinsics::_dsin:
1681       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1682                                CAST_FROM_FN_PTR(address, SharedRuntime::dsin),
1683                                "Sin", NULL, arg, top());
1684       break;
1685     case vmIntrinsics::_dcos:
1686       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1687                                CAST_FROM_FN_PTR(address, SharedRuntime::dcos),
1688                                "Cos", NULL, arg, top());
1689       break;
1690     case vmIntrinsics::_dtan:
1691       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1692                                CAST_FROM_FN_PTR(address, SharedRuntime::dtan),
1693                                "Tan", NULL, arg, top());
1694       break;
1695     }
1696     assert(control()->in(0) == call, "");
1697     Node* slow_result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
1698     r->init_req(1, control());
1699     phi->init_req(1, slow_result);
1700 
1701     // Post-merge
1702     set_control(_gvn.transform(r));
1703     record_for_igvn(r);
1704     n = _gvn.transform(phi);
1705 
1706     C->set_has_split_ifs(true); // Has chance for split-if optimization
1707   }
1708   set_result(n);
1709   return true;


1957 
1958   const TypePtr* no_memory_effects = NULL;
1959   Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
1960                                  no_memory_effects,
1961                                  a, top(), b, b ? top() : NULL);
1962   Node* value = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0));
1963 #ifdef ASSERT
1964   Node* value_top = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+1));
1965   assert(value_top == top(), "second value must be top");
1966 #endif
1967 
1968   set_result(value);
1969   return true;
1970 }
1971 
1972 //------------------------------inline_math_native-----------------------------
1973 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) {
1974 #define FN_PTR(f) CAST_FROM_FN_PTR(address, f)
1975   switch (id) {
1976     // These intrinsics are not properly supported on all hardware
1977   case vmIntrinsics::_dcos:   return Matcher::has_match_rule(Op_CosD)   ? inline_trig(id) :
1978     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos),   "COS");
1979   case vmIntrinsics::_dsin:   return Matcher::has_match_rule(Op_SinD)   ? inline_trig(id) :
1980     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin),   "SIN");




1981   case vmIntrinsics::_dtan:   return Matcher::has_match_rule(Op_TanD)   ? inline_trig(id) :
1982     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan),   "TAN");
1983 
1984   case vmIntrinsics::_dlog:
1985     return StubRoutines::dlog() != NULL ?
1986     runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
1987     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog),   "LOG");
1988   case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
1989     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");
1990 
1991     // These intrinsics are supported on all hardware
1992   case vmIntrinsics::_dsqrt:  return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false;
1993   case vmIntrinsics::_dabs:   return Matcher::has_match_rule(Op_AbsD)   ? inline_math(id) : false;
1994 
1995   case vmIntrinsics::_dexp:
1996     return StubRoutines::dexp() != NULL ?
1997       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(),  "dexp") :
1998       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp),  "EXP");
1999   case vmIntrinsics::_dpow:   return Matcher::has_match_rule(Op_PowD)   ? inline_pow()    :
2000     runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow),  "POW");




1596   Node* arg = round_double_node(argument(0));
1597   Node* n = NULL;
1598   switch (id) {
1599   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
1600   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
1601   case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg);  break;
1602   default:  fatal_unexpected_iid(id);  break;
1603   }
1604   set_result(_gvn.transform(n));
1605   return true;
1606 }
1607 
1608 //------------------------------inline_trig----------------------------------
1609 // Inline sin/cos/tan instructions, if possible.  If rounding is required, do
1610 // argument reduction which will turn into a fast/slow diamond.
1611 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
1612   Node* arg = round_double_node(argument(0));
1613   Node* n = NULL;
1614 
1615   switch (id) {


1616   case vmIntrinsics::_dtan:  n = new TanDNode(C, control(), arg);  break;
1617   default:  fatal_unexpected_iid(id);  break;
1618   }
1619   n = _gvn.transform(n);
1620 
1621   // Rounding required?  Check for argument reduction!
1622   if (Matcher::strict_fp_requires_explicit_rounding) {
1623     static const double     pi_4 =  0.7853981633974483;
1624     static const double neg_pi_4 = -0.7853981633974483;
1625     // pi/2 in 80-bit extended precision
1626     // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00};
1627     // -pi/2 in 80-bit extended precision
1628     // 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};
1629     // Cutoff value for using this argument reduction technique
1630     //static const double    pi_2_minus_epsilon =  1.564660403643354;
1631     //static const double neg_pi_2_plus_epsilon = -1.564660403643354;
1632 
1633     // Pseudocode for sin:
1634     // if (x <= Math.PI / 4.0) {
1635     //   if (x >= -Math.PI / 4.0) return  fsin(x);


1658     Node* phi = new PhiNode(r, Type::DOUBLE);
1659 
1660     // Flatten arg so we need only 1 test
1661     Node *abs = _gvn.transform(new AbsDNode(arg));
1662     // Node for PI/4 constant
1663     Node *pi4 = makecon(TypeD::make(pi_4));
1664     // Check PI/4 : abs(arg)
1665     Node *cmp = _gvn.transform(new CmpDNode(pi4,abs));
1666     // Check: If PI/4 < abs(arg) then go slow
1667     Node *bol = _gvn.transform(new BoolNode( cmp, BoolTest::lt ));
1668     // Branch either way
1669     IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
1670     set_control(opt_iff(r,iff));
1671 
1672     // Set fast path result
1673     phi->init_req(2, n);
1674 
1675     // Slow path - non-blocking leaf call
1676     Node* call = NULL;
1677     switch (id) {










1678     case vmIntrinsics::_dtan:
1679       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
1680                                CAST_FROM_FN_PTR(address, SharedRuntime::dtan),
1681                                "Tan", NULL, arg, top());
1682       break;
1683     }
1684     assert(control()->in(0) == call, "");
1685     Node* slow_result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
1686     r->init_req(1, control());
1687     phi->init_req(1, slow_result);
1688 
1689     // Post-merge
1690     set_control(_gvn.transform(r));
1691     record_for_igvn(r);
1692     n = _gvn.transform(phi);
1693 
1694     C->set_has_split_ifs(true); // Has chance for split-if optimization
1695   }
1696   set_result(n);
1697   return true;


1945 
1946   const TypePtr* no_memory_effects = NULL;
1947   Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
1948                                  no_memory_effects,
1949                                  a, top(), b, b ? top() : NULL);
1950   Node* value = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0));
1951 #ifdef ASSERT
1952   Node* value_top = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+1));
1953   assert(value_top == top(), "second value must be top");
1954 #endif
1955 
1956   set_result(value);
1957   return true;
1958 }
1959 
1960 //------------------------------inline_math_native-----------------------------
1961 bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) {
1962 #define FN_PTR(f) CAST_FROM_FN_PTR(address, f)
1963   switch (id) {
1964     // These intrinsics are not properly supported on all hardware
1965   case vmIntrinsics::_dsin:
1966     return StubRoutines::dsin() != NULL ?
1967       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dsin(), "dsin") :
1968       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dsin),   "SIN");
1969   case vmIntrinsics::_dcos:
1970     return StubRoutines::dcos() != NULL ?
1971       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dcos(), "dcos") :
1972       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dcos),   "COS");
1973   case vmIntrinsics::_dtan:   return Matcher::has_match_rule(Op_TanD)   ? inline_trig(id) :
1974     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan),   "TAN");
1975 
1976   case vmIntrinsics::_dlog:
1977     return StubRoutines::dlog() != NULL ?
1978       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
1979       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog),   "LOG");
1980   case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
1981     runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");
1982 
1983     // These intrinsics are supported on all hardware
1984   case vmIntrinsics::_dsqrt:  return Matcher::match_rule_supported(Op_SqrtD) ? inline_math(id) : false;
1985   case vmIntrinsics::_dabs:   return Matcher::has_match_rule(Op_AbsD)   ? inline_math(id) : false;
1986 
1987   case vmIntrinsics::_dexp:
1988     return StubRoutines::dexp() != NULL ?
1989       runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dexp(),  "dexp") :
1990       runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dexp),  "EXP");
1991   case vmIntrinsics::_dpow:   return Matcher::has_match_rule(Op_PowD)   ? inline_pow()    :
1992     runtime_math(OptoRuntime::Math_DD_D_Type(), FN_PTR(SharedRuntime::dpow),  "POW");


< prev index next >