Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/library_call.cpp @ 681:fbde8ec322d0
6761600: Use sse 4.2 in intrinsics
Summary: Use SSE 4.2 in intrinsics for String.{compareTo/equals/indexOf} and Arrays.equals.
Reviewed-by: kvn, never, jrose
author | cfang |
---|---|
date | Tue, 31 Mar 2009 14:07:08 -0700 |
parents | c771b7f43bbf |
children | 9c6be3edf0dc |
comparison
equal
deleted
inserted
replaced
676:d3676b4cb78c | 681:fbde8ec322d0 |
---|---|
134 } | 134 } |
135 | 135 |
136 bool inline_string_compareTo(); | 136 bool inline_string_compareTo(); |
137 bool inline_string_indexOf(); | 137 bool inline_string_indexOf(); |
138 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); | 138 Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i); |
139 bool inline_string_equals(); | |
139 Node* pop_math_arg(); | 140 Node* pop_math_arg(); |
140 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); | 141 bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName); |
141 bool inline_math_native(vmIntrinsics::ID id); | 142 bool inline_math_native(vmIntrinsics::ID id); |
142 bool inline_trig(vmIntrinsics::ID id); | 143 bool inline_trig(vmIntrinsics::ID id); |
143 bool inline_trans(vmIntrinsics::ID id); | 144 bool inline_trans(vmIntrinsics::ID id); |
259 // -XX:-InlineNatives disables nearly all intrinsics: | 260 // -XX:-InlineNatives disables nearly all intrinsics: |
260 if (!InlineNatives) { | 261 if (!InlineNatives) { |
261 switch (id) { | 262 switch (id) { |
262 case vmIntrinsics::_indexOf: | 263 case vmIntrinsics::_indexOf: |
263 case vmIntrinsics::_compareTo: | 264 case vmIntrinsics::_compareTo: |
265 case vmIntrinsics::_equals: | |
264 case vmIntrinsics::_equalsC: | 266 case vmIntrinsics::_equalsC: |
265 break; // InlineNatives does not control String.compareTo | 267 break; // InlineNatives does not control String.compareTo |
266 default: | 268 default: |
267 return NULL; | 269 return NULL; |
268 } | 270 } |
272 case vmIntrinsics::_compareTo: | 274 case vmIntrinsics::_compareTo: |
273 if (!SpecialStringCompareTo) return NULL; | 275 if (!SpecialStringCompareTo) return NULL; |
274 break; | 276 break; |
275 case vmIntrinsics::_indexOf: | 277 case vmIntrinsics::_indexOf: |
276 if (!SpecialStringIndexOf) return NULL; | 278 if (!SpecialStringIndexOf) return NULL; |
279 break; | |
280 case vmIntrinsics::_equals: | |
281 if (!SpecialStringEquals) return NULL; | |
277 break; | 282 break; |
278 case vmIntrinsics::_equalsC: | 283 case vmIntrinsics::_equalsC: |
279 if (!SpecialArraysEquals) return NULL; | 284 if (!SpecialArraysEquals) return NULL; |
280 break; | 285 break; |
281 case vmIntrinsics::_arraycopy: | 286 case vmIntrinsics::_arraycopy: |
440 | 445 |
441 case vmIntrinsics::_compareTo: | 446 case vmIntrinsics::_compareTo: |
442 return inline_string_compareTo(); | 447 return inline_string_compareTo(); |
443 case vmIntrinsics::_indexOf: | 448 case vmIntrinsics::_indexOf: |
444 return inline_string_indexOf(); | 449 return inline_string_indexOf(); |
450 case vmIntrinsics::_equals: | |
451 return inline_string_equals(); | |
445 | 452 |
446 case vmIntrinsics::_getObject: | 453 case vmIntrinsics::_getObject: |
447 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); | 454 return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, false); |
448 case vmIntrinsics::_getBoolean: | 455 case vmIntrinsics::_getBoolean: |
449 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false); | 456 return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, false); |
791 | 798 |
792 | 799 |
793 //------------------------------inline_string_compareTo------------------------ | 800 //------------------------------inline_string_compareTo------------------------ |
794 bool LibraryCallKit::inline_string_compareTo() { | 801 bool LibraryCallKit::inline_string_compareTo() { |
795 | 802 |
803 if (!Matcher::has_match_rule(Op_StrComp)) return false; | |
804 | |
796 const int value_offset = java_lang_String::value_offset_in_bytes(); | 805 const int value_offset = java_lang_String::value_offset_in_bytes(); |
797 const int count_offset = java_lang_String::count_offset_in_bytes(); | 806 const int count_offset = java_lang_String::count_offset_in_bytes(); |
798 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | 807 const int offset_offset = java_lang_String::offset_offset_in_bytes(); |
799 | 808 |
800 _sp += 2; | 809 _sp += 2; |
825 memory(string_type->add_offset(count_offset)), | 834 memory(string_type->add_offset(count_offset)), |
826 memory(string_type->add_offset(offset_offset)), | 835 memory(string_type->add_offset(offset_offset)), |
827 receiver, | 836 receiver, |
828 argument)); | 837 argument)); |
829 push(compare); | 838 push(compare); |
839 return true; | |
840 } | |
841 | |
842 //------------------------------inline_string_equals------------------------ | |
843 bool LibraryCallKit::inline_string_equals() { | |
844 | |
845 if (!Matcher::has_match_rule(Op_StrEquals)) return false; | |
846 | |
847 const int value_offset = java_lang_String::value_offset_in_bytes(); | |
848 const int count_offset = java_lang_String::count_offset_in_bytes(); | |
849 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
850 | |
851 _sp += 2; | |
852 Node* argument = pop(); // pop non-receiver first: it was pushed second | |
853 Node* receiver = pop(); | |
854 | |
855 // Null check on self without removing any arguments. The argument | |
856 // null check technically happens in the wrong place, which can lead to | |
857 // invalid stack traces when string compare is inlined into a method | |
858 // which handles NullPointerExceptions. | |
859 _sp += 2; | |
860 receiver = do_null_check(receiver, T_OBJECT); | |
861 //should not do null check for argument for String.equals(), because spec | |
862 //allows to specify NULL as argument. | |
863 _sp -= 2; | |
864 | |
865 if (stopped()) { | |
866 return true; | |
867 } | |
868 | |
869 // get String klass for instanceOf | |
870 ciInstanceKlass* klass = env()->String_klass(); | |
871 | |
872 // two paths (plus control) merge | |
873 RegionNode* region = new (C, 3) RegionNode(3); | |
874 Node* phi = new (C, 3) PhiNode(region, TypeInt::BOOL); | |
875 | |
876 Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass))); | |
877 Node* cmp = _gvn.transform(new (C, 3) CmpINode(inst, intcon(1))); | |
878 Node* bol = _gvn.transform(new (C, 2) BoolNode(cmp, BoolTest::eq)); | |
879 | |
880 IfNode* iff = create_and_map_if(control(), bol, PROB_MAX, COUNT_UNKNOWN); | |
881 | |
882 Node* if_true = _gvn.transform(new (C, 1) IfTrueNode(iff)); | |
883 set_control(if_true); | |
884 | |
885 const TypeInstPtr* string_type = | |
886 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); | |
887 | |
888 // instanceOf == true | |
889 Node* equals = | |
890 _gvn.transform(new (C, 7) StrEqualsNode( | |
891 control(), | |
892 memory(TypeAryPtr::CHARS), | |
893 memory(string_type->add_offset(value_offset)), | |
894 memory(string_type->add_offset(count_offset)), | |
895 memory(string_type->add_offset(offset_offset)), | |
896 receiver, | |
897 argument)); | |
898 | |
899 phi->init_req(1, _gvn.transform(equals)); | |
900 region->init_req(1, if_true); | |
901 | |
902 //instanceOf == false, fallthrough | |
903 Node* if_false = _gvn.transform(new (C, 1) IfFalseNode(iff)); | |
904 set_control(if_false); | |
905 | |
906 phi->init_req(2, _gvn.transform(intcon(0))); | |
907 region->init_req(2, if_false); | |
908 | |
909 // post merge | |
910 set_control(_gvn.transform(region)); | |
911 record_for_igvn(region); | |
912 | |
913 push(_gvn.transform(phi)); | |
914 | |
830 return true; | 915 return true; |
831 } | 916 } |
832 | 917 |
833 //------------------------------inline_array_equals---------------------------- | 918 //------------------------------inline_array_equals---------------------------- |
834 bool LibraryCallKit::inline_array_equals() { | 919 bool LibraryCallKit::inline_array_equals() { |
992 #undef __ | 1077 #undef __ |
993 C->set_has_loops(true); | 1078 C->set_has_loops(true); |
994 return result; | 1079 return result; |
995 } | 1080 } |
996 | 1081 |
997 | |
998 //------------------------------inline_string_indexOf------------------------ | 1082 //------------------------------inline_string_indexOf------------------------ |
999 bool LibraryCallKit::inline_string_indexOf() { | 1083 bool LibraryCallKit::inline_string_indexOf() { |
1084 | |
1085 const int value_offset = java_lang_String::value_offset_in_bytes(); | |
1086 const int count_offset = java_lang_String::count_offset_in_bytes(); | |
1087 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | |
1000 | 1088 |
1001 _sp += 2; | 1089 _sp += 2; |
1002 Node *argument = pop(); // pop non-receiver first: it was pushed second | 1090 Node *argument = pop(); // pop non-receiver first: it was pushed second |
1003 Node *receiver = pop(); | 1091 Node *receiver = pop(); |
1004 | 1092 |
1005 // don't intrinsify if argument isn't a constant string. | 1093 Node* result; |
1006 if (!argument->is_Con()) { | 1094 if (Matcher::has_match_rule(Op_StrIndexOf) && |
1007 return false; | 1095 UseSSE42Intrinsics) { |
1008 } | 1096 // Generate SSE4.2 version of indexOf |
1009 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); | 1097 // We currently only have match rules that use SSE4.2 |
1010 if (str_type == NULL) { | 1098 |
1011 return false; | 1099 // Null check on self without removing any arguments. The argument |
1012 } | 1100 // null check technically happens in the wrong place, which can lead to |
1013 ciInstanceKlass* klass = env()->String_klass(); | 1101 // invalid stack traces when string compare is inlined into a method |
1014 ciObject* str_const = str_type->const_oop(); | 1102 // which handles NullPointerExceptions. |
1015 if (str_const == NULL || str_const->klass() != klass) { | 1103 _sp += 2; |
1016 return false; | 1104 receiver = do_null_check(receiver, T_OBJECT); |
1017 } | 1105 argument = do_null_check(argument, T_OBJECT); |
1018 ciInstance* str = str_const->as_instance(); | 1106 _sp -= 2; |
1019 assert(str != NULL, "must be instance"); | 1107 |
1020 | 1108 if (stopped()) { |
1021 const int value_offset = java_lang_String::value_offset_in_bytes(); | 1109 return true; |
1022 const int count_offset = java_lang_String::count_offset_in_bytes(); | 1110 } |
1023 const int offset_offset = java_lang_String::offset_offset_in_bytes(); | 1111 |
1024 | 1112 ciInstanceKlass* klass = env()->String_klass(); |
1025 ciObject* v = str->field_value_by_offset(value_offset).as_object(); | 1113 const TypeInstPtr* string_type = |
1026 int o = str->field_value_by_offset(offset_offset).as_int(); | 1114 TypeInstPtr::make(TypePtr::BotPTR, klass, false, NULL, 0); |
1027 int c = str->field_value_by_offset(count_offset).as_int(); | 1115 |
1028 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array | 1116 result = |
1029 | 1117 _gvn.transform(new (C, 7) |
1030 // constant strings have no offset and count == length which | 1118 StrIndexOfNode(control(), |
1031 // simplifies the resulting code somewhat so lets optimize for that. | 1119 memory(TypeAryPtr::CHARS), |
1032 if (o != 0 || c != pat->length()) { | 1120 memory(string_type->add_offset(value_offset)), |
1033 return false; | 1121 memory(string_type->add_offset(count_offset)), |
1034 } | 1122 memory(string_type->add_offset(offset_offset)), |
1035 | 1123 receiver, |
1036 // Null check on self without removing any arguments. The argument | 1124 argument)); |
1037 // null check technically happens in the wrong place, which can lead to | 1125 } else { //Use LibraryCallKit::string_indexOf |
1038 // invalid stack traces when string compare is inlined into a method | 1126 // don't intrinsify is argument isn't a constant string. |
1039 // which handles NullPointerExceptions. | 1127 if (!argument->is_Con()) { |
1040 _sp += 2; | 1128 return false; |
1041 receiver = do_null_check(receiver, T_OBJECT); | 1129 } |
1042 // No null check on the argument is needed since it's a constant String oop. | 1130 const TypeOopPtr* str_type = _gvn.type(argument)->isa_oopptr(); |
1043 _sp -= 2; | 1131 if (str_type == NULL) { |
1044 if (stopped()) { | 1132 return false; |
1045 return true; | 1133 } |
1046 } | 1134 ciInstanceKlass* klass = env()->String_klass(); |
1047 | 1135 ciObject* str_const = str_type->const_oop(); |
1048 // The null string as a pattern always returns 0 (match at beginning of string) | 1136 if (str_const == NULL || str_const->klass() != klass) { |
1049 if (c == 0) { | 1137 return false; |
1050 push(intcon(0)); | 1138 } |
1051 return true; | 1139 ciInstance* str = str_const->as_instance(); |
1052 } | 1140 assert(str != NULL, "must be instance"); |
1053 | 1141 |
1054 jchar lastChar = pat->char_at(o + (c - 1)); | 1142 ciObject* v = str->field_value_by_offset(value_offset).as_object(); |
1055 int cache = 0; | 1143 int o = str->field_value_by_offset(offset_offset).as_int(); |
1056 int i; | 1144 int c = str->field_value_by_offset(count_offset).as_int(); |
1057 for (i = 0; i < c - 1; i++) { | 1145 ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array |
1058 assert(i < pat->length(), "out of range"); | 1146 |
1059 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); | 1147 // constant strings have no offset and count == length which |
1060 } | 1148 // simplifies the resulting code somewhat so lets optimize for that. |
1061 | 1149 if (o != 0 || c != pat->length()) { |
1062 int md2 = c; | 1150 return false; |
1063 for (i = 0; i < c - 1; i++) { | 1151 } |
1064 assert(i < pat->length(), "out of range"); | 1152 |
1065 if (pat->char_at(o + i) == lastChar) { | 1153 // Null check on self without removing any arguments. The argument |
1066 md2 = (c - 1) - i; | 1154 // null check technically happens in the wrong place, which can lead to |
1067 } | 1155 // invalid stack traces when string compare is inlined into a method |
1068 } | 1156 // which handles NullPointerExceptions. |
1069 | 1157 _sp += 2; |
1070 Node* result = string_indexOf(receiver, pat, o, cache, md2); | 1158 receiver = do_null_check(receiver, T_OBJECT); |
1159 // No null check on the argument is needed since it's a constant String oop. | |
1160 _sp -= 2; | |
1161 if (stopped()) { | |
1162 return true; | |
1163 } | |
1164 | |
1165 // The null string as a pattern always returns 0 (match at beginning of string) | |
1166 if (c == 0) { | |
1167 push(intcon(0)); | |
1168 return true; | |
1169 } | |
1170 | |
1171 // Generate default indexOf | |
1172 jchar lastChar = pat->char_at(o + (c - 1)); | |
1173 int cache = 0; | |
1174 int i; | |
1175 for (i = 0; i < c - 1; i++) { | |
1176 assert(i < pat->length(), "out of range"); | |
1177 cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1))); | |
1178 } | |
1179 | |
1180 int md2 = c; | |
1181 for (i = 0; i < c - 1; i++) { | |
1182 assert(i < pat->length(), "out of range"); | |
1183 if (pat->char_at(o + i) == lastChar) { | |
1184 md2 = (c - 1) - i; | |
1185 } | |
1186 } | |
1187 | |
1188 result = string_indexOf(receiver, pat, o, cache, md2); | |
1189 } | |
1190 | |
1071 push(result); | 1191 push(result); |
1072 return true; | 1192 return true; |
1073 } | 1193 } |
1074 | 1194 |
1075 //--------------------------pop_math_arg-------------------------------- | 1195 //--------------------------pop_math_arg-------------------------------- |