hotspot/src/share/vm/opto/library_call.cpp
changeset 40044 4e8299073922
parent 39419 cc993a4ab581
child 40045 4273f3ba95f7
equal deleted inserted replaced
40043:983696c33883 40044:4e8299073922
   220   bool inline_string_copy(bool compress);
   220   bool inline_string_copy(bool compress);
   221   bool inline_string_char_access(bool is_store);
   221   bool inline_string_char_access(bool is_store);
   222   Node* round_double_node(Node* n);
   222   Node* round_double_node(Node* n);
   223   bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
   223   bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
   224   bool inline_math_native(vmIntrinsics::ID id);
   224   bool inline_math_native(vmIntrinsics::ID id);
   225   bool inline_trig(vmIntrinsics::ID id);
       
   226   bool inline_math(vmIntrinsics::ID id);
   225   bool inline_math(vmIntrinsics::ID id);
   227   template <typename OverflowOp>
   226   template <typename OverflowOp>
   228   bool inline_math_overflow(Node* arg1, Node* arg2);
   227   bool inline_math_overflow(Node* arg1, Node* arg2);
   229   void inline_math_mathExact(Node* math, Node* test);
   228   void inline_math_mathExact(Node* math, Node* test);
   230   bool inline_math_addExactI(bool is_increment);
   229   bool inline_math_addExactI(bool is_increment);
  1686   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
  1685   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
  1687   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
  1686   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
  1688   default:  fatal_unexpected_iid(id);  break;
  1687   default:  fatal_unexpected_iid(id);  break;
  1689   }
  1688   }
  1690   set_result(_gvn.transform(n));
  1689   set_result(_gvn.transform(n));
  1691   return true;
       
  1692 }
       
  1693 
       
  1694 //------------------------------inline_trig----------------------------------
       
  1695 // Inline sin/cos/tan instructions, if possible.  If rounding is required, do
       
  1696 // argument reduction which will turn into a fast/slow diamond.
       
  1697 bool LibraryCallKit::inline_trig(vmIntrinsics::ID id) {
       
  1698   Node* arg = round_double_node(argument(0));
       
  1699   Node* n = NULL;
       
  1700 
       
  1701   n = _gvn.transform(n);
       
  1702 
       
  1703   // Rounding required?  Check for argument reduction!
       
  1704   if (Matcher::strict_fp_requires_explicit_rounding) {
       
  1705     static const double     pi_4 =  0.7853981633974483;
       
  1706     static const double neg_pi_4 = -0.7853981633974483;
       
  1707     // pi/2 in 80-bit extended precision
       
  1708     // static const unsigned char pi_2_bits_x[] = {0x35,0xc2,0x68,0x21,0xa2,0xda,0x0f,0xc9,0xff,0x3f,0x00,0x00,0x00,0x00,0x00,0x00};
       
  1709     // -pi/2 in 80-bit extended precision
       
  1710     // 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};
       
  1711     // Cutoff value for using this argument reduction technique
       
  1712     //static const double    pi_2_minus_epsilon =  1.564660403643354;
       
  1713     //static const double neg_pi_2_plus_epsilon = -1.564660403643354;
       
  1714 
       
  1715     // Pseudocode for sin:
       
  1716     // if (x <= Math.PI / 4.0) {
       
  1717     //   if (x >= -Math.PI / 4.0) return  fsin(x);
       
  1718     //   if (x >= -Math.PI / 2.0) return -fcos(x + Math.PI / 2.0);
       
  1719     // } else {
       
  1720     //   if (x <=  Math.PI / 2.0) return  fcos(x - Math.PI / 2.0);
       
  1721     // }
       
  1722     // return StrictMath.sin(x);
       
  1723 
       
  1724     // Pseudocode for cos:
       
  1725     // if (x <= Math.PI / 4.0) {
       
  1726     //   if (x >= -Math.PI / 4.0) return  fcos(x);
       
  1727     //   if (x >= -Math.PI / 2.0) return  fsin(x + Math.PI / 2.0);
       
  1728     // } else {
       
  1729     //   if (x <=  Math.PI / 2.0) return -fsin(x - Math.PI / 2.0);
       
  1730     // }
       
  1731     // return StrictMath.cos(x);
       
  1732 
       
  1733     // Actually, sticking in an 80-bit Intel value into C2 will be tough; it
       
  1734     // requires a special machine instruction to load it.  Instead we'll try
       
  1735     // the 'easy' case.  If we really need the extra range +/- PI/2 we'll
       
  1736     // probably do the math inside the SIN encoding.
       
  1737 
       
  1738     // Make the merge point
       
  1739     RegionNode* r = new RegionNode(3);
       
  1740     Node* phi = new PhiNode(r, Type::DOUBLE);
       
  1741 
       
  1742     // Flatten arg so we need only 1 test
       
  1743     Node *abs = _gvn.transform(new AbsDNode(arg));
       
  1744     // Node for PI/4 constant
       
  1745     Node *pi4 = makecon(TypeD::make(pi_4));
       
  1746     // Check PI/4 : abs(arg)
       
  1747     Node *cmp = _gvn.transform(new CmpDNode(pi4,abs));
       
  1748     // Check: If PI/4 < abs(arg) then go slow
       
  1749     Node *bol = _gvn.transform(new BoolNode( cmp, BoolTest::lt ));
       
  1750     // Branch either way
       
  1751     IfNode *iff = create_and_xform_if(control(),bol, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
       
  1752     set_control(opt_iff(r,iff));
       
  1753 
       
  1754     // Set fast path result
       
  1755     phi->init_req(2, n);
       
  1756 
       
  1757     // Slow path - non-blocking leaf call
       
  1758     Node* call = NULL;
       
  1759     switch (id) {
       
  1760     case vmIntrinsics::_dtan:
       
  1761       call = make_runtime_call(RC_LEAF, OptoRuntime::Math_D_D_Type(),
       
  1762                                CAST_FROM_FN_PTR(address, SharedRuntime::dtan),
       
  1763                                "Tan", NULL, arg, top());
       
  1764       break;
       
  1765     }
       
  1766     assert(control()->in(0) == call, "");
       
  1767     Node* slow_result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
       
  1768     r->init_req(1, control());
       
  1769     phi->init_req(1, slow_result);
       
  1770 
       
  1771     // Post-merge
       
  1772     set_control(_gvn.transform(r));
       
  1773     record_for_igvn(r);
       
  1774     n = _gvn.transform(phi);
       
  1775 
       
  1776     C->set_has_split_ifs(true); // Has chance for split-if optimization
       
  1777   }
       
  1778   set_result(n);
       
  1779   return true;
  1690   return true;
  1780 }
  1691 }
  1781 
  1692 
  1782 //------------------------------runtime_math-----------------------------
  1693 //------------------------------runtime_math-----------------------------
  1783 bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) {
  1694 bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName) {