comparison src/share/vm/opto/library_call.cpp @ 17726:085b304a1cc5

8027754: Enable loop optimizations for loops with MathExact inside Reviewed-by: kvn, iveresov
author rbackman
date Thu, 23 Jan 2014 12:08:28 +0100
parents cdb71841f4bc
children 9ab9f254cfe2
comparison
equal deleted inserted replaced
17725:b4ce4e9eb97d 17726:085b304a1cc5
201 Node* round_double_node(Node* n); 201 Node* round_double_node(Node* n);
202 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); 202 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
203 bool inline_math_native(vmIntrinsics::ID id); 203 bool inline_math_native(vmIntrinsics::ID id);
204 bool inline_trig(vmIntrinsics::ID id); 204 bool inline_trig(vmIntrinsics::ID id);
205 bool inline_math(vmIntrinsics::ID id); 205 bool inline_math(vmIntrinsics::ID id);
206 void inline_math_mathExact(Node* math); 206 template <typename OverflowOp>
207 bool inline_math_overflow(Node* arg1, Node* arg2);
208 void inline_math_mathExact(Node* math, Node* test);
207 bool inline_math_addExactI(bool is_increment); 209 bool inline_math_addExactI(bool is_increment);
208 bool inline_math_addExactL(bool is_increment); 210 bool inline_math_addExactL(bool is_increment);
209 bool inline_math_multiplyExactI(); 211 bool inline_math_multiplyExactI();
210 bool inline_math_multiplyExactL(); 212 bool inline_math_multiplyExactL();
211 bool inline_math_negateExactI(); 213 bool inline_math_negateExactI();
515 if (!UseCRC32Intrinsics) return NULL; 517 if (!UseCRC32Intrinsics) return NULL;
516 break; 518 break;
517 519
518 case vmIntrinsics::_incrementExactI: 520 case vmIntrinsics::_incrementExactI:
519 case vmIntrinsics::_addExactI: 521 case vmIntrinsics::_addExactI:
520 if (!Matcher::match_rule_supported(Op_AddExactI) || !UseMathExactIntrinsics) return NULL; 522 if (!Matcher::match_rule_supported(Op_OverflowAddI) || !UseMathExactIntrinsics) return NULL;
521 break; 523 break;
522 case vmIntrinsics::_incrementExactL: 524 case vmIntrinsics::_incrementExactL:
523 case vmIntrinsics::_addExactL: 525 case vmIntrinsics::_addExactL:
524 if (!Matcher::match_rule_supported(Op_AddExactL) || !UseMathExactIntrinsics) return NULL; 526 if (!Matcher::match_rule_supported(Op_OverflowAddL) || !UseMathExactIntrinsics) return NULL;
525 break; 527 break;
526 case vmIntrinsics::_decrementExactI: 528 case vmIntrinsics::_decrementExactI:
527 case vmIntrinsics::_subtractExactI: 529 case vmIntrinsics::_subtractExactI:
528 if (!Matcher::match_rule_supported(Op_SubExactI) || !UseMathExactIntrinsics) return NULL; 530 if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL;
529 break; 531 break;
530 case vmIntrinsics::_decrementExactL: 532 case vmIntrinsics::_decrementExactL:
531 case vmIntrinsics::_subtractExactL: 533 case vmIntrinsics::_subtractExactL:
532 if (!Matcher::match_rule_supported(Op_SubExactL) || !UseMathExactIntrinsics) return NULL; 534 if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL;
533 break; 535 break;
534 case vmIntrinsics::_negateExactI: 536 case vmIntrinsics::_negateExactI:
535 if (!Matcher::match_rule_supported(Op_NegExactI) || !UseMathExactIntrinsics) return NULL; 537 if (!Matcher::match_rule_supported(Op_OverflowSubI) || !UseMathExactIntrinsics) return NULL;
536 break; 538 break;
537 case vmIntrinsics::_negateExactL: 539 case vmIntrinsics::_negateExactL:
538 if (!Matcher::match_rule_supported(Op_NegExactL) || !UseMathExactIntrinsics) return NULL; 540 if (!Matcher::match_rule_supported(Op_OverflowSubL) || !UseMathExactIntrinsics) return NULL;
539 break; 541 break;
540 case vmIntrinsics::_multiplyExactI: 542 case vmIntrinsics::_multiplyExactI:
541 if (!Matcher::match_rule_supported(Op_MulExactI) || !UseMathExactIntrinsics) return NULL; 543 if (!Matcher::match_rule_supported(Op_OverflowMulI) || !UseMathExactIntrinsics) return NULL;
542 break; 544 break;
543 case vmIntrinsics::_multiplyExactL: 545 case vmIntrinsics::_multiplyExactL:
544 if (!Matcher::match_rule_supported(Op_MulExactL) || !UseMathExactIntrinsics) return NULL; 546 if (!Matcher::match_rule_supported(Op_OverflowMulL) || !UseMathExactIntrinsics) return NULL;
545 break; 547 break;
546 548
547 default: 549 default:
548 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility"); 550 assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
549 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); 551 assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?");
1968 bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) { 1970 bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) {
1969 set_result(generate_min_max(id, argument(0), argument(1))); 1971 set_result(generate_min_max(id, argument(0), argument(1)));
1970 return true; 1972 return true;
1971 } 1973 }
1972 1974
1973 void LibraryCallKit::inline_math_mathExact(Node* math) { 1975 void LibraryCallKit::inline_math_mathExact(Node* math, Node *test) {
1974 // If we didn't get the expected opcode it means we have optimized 1976 Node* bol = _gvn.transform( new (C) BoolNode(test, BoolTest::overflow) );
1975 // the node to something else and don't need the exception edge.
1976 if (!math->is_MathExact()) {
1977 set_result(math);
1978 return;
1979 }
1980
1981 Node* result = _gvn.transform( new(C) ProjNode(math, MathExactNode::result_proj_node));
1982 Node* flags = _gvn.transform( new(C) FlagsProjNode(math, MathExactNode::flags_proj_node));
1983
1984 Node* bol = _gvn.transform( new (C) BoolNode(flags, BoolTest::overflow) );
1985 IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); 1977 IfNode* check = create_and_map_if(control(), bol, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN);
1986 Node* fast_path = _gvn.transform( new (C) IfFalseNode(check)); 1978 Node* fast_path = _gvn.transform( new (C) IfFalseNode(check));
1987 Node* slow_path = _gvn.transform( new (C) IfTrueNode(check) ); 1979 Node* slow_path = _gvn.transform( new (C) IfTrueNode(check) );
1988 1980
1989 { 1981 {
1997 uncommon_trap(Deoptimization::Reason_intrinsic, 1989 uncommon_trap(Deoptimization::Reason_intrinsic,
1998 Deoptimization::Action_none); 1990 Deoptimization::Action_none);
1999 } 1991 }
2000 1992
2001 set_control(fast_path); 1993 set_control(fast_path);
2002 set_result(result); 1994 set_result(math);
1995 }
1996
1997 template <typename OverflowOp>
1998 bool LibraryCallKit::inline_math_overflow(Node* arg1, Node* arg2) {
1999 typedef typename OverflowOp::MathOp MathOp;
2000
2001 MathOp* mathOp = new(C) MathOp(arg1, arg2);
2002 Node* operation = _gvn.transform( mathOp );
2003 Node* ofcheck = _gvn.transform( new(C) OverflowOp(arg1, arg2) );
2004 inline_math_mathExact(operation, ofcheck);
2005 return true;
2003 } 2006 }
2004 2007
2005 bool LibraryCallKit::inline_math_addExactI(bool is_increment) { 2008 bool LibraryCallKit::inline_math_addExactI(bool is_increment) {
2006 Node* arg1 = argument(0); 2009 return inline_math_overflow<OverflowAddINode>(argument(0), is_increment ? intcon(1) : argument(1));
2007 Node* arg2 = NULL;
2008
2009 if (is_increment) {
2010 arg2 = intcon(1);
2011 } else {
2012 arg2 = argument(1);
2013 }
2014
2015 Node* add = _gvn.transform( new(C) AddExactINode(NULL, arg1, arg2) );
2016 inline_math_mathExact(add);
2017 return true;
2018 } 2010 }
2019 2011
2020 bool LibraryCallKit::inline_math_addExactL(bool is_increment) { 2012 bool LibraryCallKit::inline_math_addExactL(bool is_increment) {
2021 Node* arg1 = argument(0); // type long 2013 return inline_math_overflow<OverflowAddLNode>(argument(0), is_increment ? longcon(1) : argument(2));
2022 // argument(1) == TOP
2023 Node* arg2 = NULL;
2024
2025 if (is_increment) {
2026 arg2 = longcon(1);
2027 } else {
2028 arg2 = argument(2); // type long
2029 // argument(3) == TOP
2030 }
2031
2032 Node* add = _gvn.transform(new(C) AddExactLNode(NULL, arg1, arg2));
2033 inline_math_mathExact(add);
2034 return true;
2035 } 2014 }
2036 2015
2037 bool LibraryCallKit::inline_math_subtractExactI(bool is_decrement) { 2016 bool LibraryCallKit::inline_math_subtractExactI(bool is_decrement) {
2038 Node* arg1 = argument(0); 2017 return inline_math_overflow<OverflowSubINode>(argument(0), is_decrement ? intcon(1) : argument(1));
2039 Node* arg2 = NULL;
2040
2041 if (is_decrement) {
2042 arg2 = intcon(1);
2043 } else {
2044 arg2 = argument(1);
2045 }
2046
2047 Node* sub = _gvn.transform(new(C) SubExactINode(NULL, arg1, arg2));
2048 inline_math_mathExact(sub);
2049 return true;
2050 } 2018 }
2051 2019
2052 bool LibraryCallKit::inline_math_subtractExactL(bool is_decrement) { 2020 bool LibraryCallKit::inline_math_subtractExactL(bool is_decrement) {
2053 Node* arg1 = argument(0); // type long 2021 return inline_math_overflow<OverflowSubLNode>(argument(0), is_decrement ? longcon(1) : argument(2));
2054 // argument(1) == TOP
2055 Node* arg2 = NULL;
2056
2057 if (is_decrement) {
2058 arg2 = longcon(1);
2059 } else {
2060 arg2 = argument(2); // type long
2061 // argument(3) == TOP
2062 }
2063
2064 Node* sub = _gvn.transform(new(C) SubExactLNode(NULL, arg1, arg2));
2065 inline_math_mathExact(sub);
2066 return true;
2067 } 2022 }
2068 2023
2069 bool LibraryCallKit::inline_math_negateExactI() { 2024 bool LibraryCallKit::inline_math_negateExactI() {
2070 Node* arg1 = argument(0); 2025 return inline_math_overflow<OverflowSubINode>(intcon(0), argument(0));
2071
2072 Node* neg = _gvn.transform(new(C) NegExactINode(NULL, arg1));
2073 inline_math_mathExact(neg);
2074 return true;
2075 } 2026 }
2076 2027
2077 bool LibraryCallKit::inline_math_negateExactL() { 2028 bool LibraryCallKit::inline_math_negateExactL() {
2078 Node* arg1 = argument(0); 2029 return inline_math_overflow<OverflowSubLNode>(longcon(0), argument(0));
2079 // argument(1) == TOP
2080
2081 Node* neg = _gvn.transform(new(C) NegExactLNode(NULL, arg1));
2082 inline_math_mathExact(neg);
2083 return true;
2084 } 2030 }
2085 2031
2086 bool LibraryCallKit::inline_math_multiplyExactI() { 2032 bool LibraryCallKit::inline_math_multiplyExactI() {
2087 Node* arg1 = argument(0); 2033 return inline_math_overflow<OverflowMulINode>(argument(0), argument(1));
2088 Node* arg2 = argument(1);
2089
2090 Node* mul = _gvn.transform(new(C) MulExactINode(NULL, arg1, arg2));
2091 inline_math_mathExact(mul);
2092 return true;
2093 } 2034 }
2094 2035
2095 bool LibraryCallKit::inline_math_multiplyExactL() { 2036 bool LibraryCallKit::inline_math_multiplyExactL() {
2096 Node* arg1 = argument(0); 2037 return inline_math_overflow<OverflowMulLNode>(argument(0), argument(2));
2097 // argument(1) == TOP
2098 Node* arg2 = argument(2);
2099 // argument(3) == TOP
2100
2101 Node* mul = _gvn.transform(new(C) MulExactLNode(NULL, arg1, arg2));
2102 inline_math_mathExact(mul);
2103 return true;
2104 } 2038 }
2105 2039
2106 Node* 2040 Node*
2107 LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) { 2041 LibraryCallKit::generate_min_max(vmIntrinsics::ID id, Node* x0, Node* y0) {
2108 // These are the candidate return value: 2042 // These are the candidate return value: