Mercurial > hg > truffle
comparison src/cpu/sparc/vm/sparc.ad @ 986:62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
6875866: Intrinsic for String.indexOf() is broken on x86 with SSE4.2
Summary: Modify String intrinsic methods to pass char[] pointers instead of string oops.
Reviewed-by: never
author | kvn |
---|---|
date | Mon, 14 Sep 2009 12:14:20 -0700 |
parents | 1fbd5d696bf4 |
children | 1ce3281a8e93 |
comparison
equal
deleted
inserted
replaced
985:685e959d09ea | 986:62001a362ce9 |
---|---|
2836 __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); | 2836 __ delayed()-> stx(G0, base_pointer_arg, nof_bytes_tmp); |
2837 // %%%% this mini-loop must not cross a cache boundary! | 2837 // %%%% this mini-loop must not cross a cache boundary! |
2838 %} | 2838 %} |
2839 | 2839 |
2840 | 2840 |
2841 enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ | 2841 enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{ |
2842 Label Ldone, Lloop; | 2842 Label Ldone, Lloop; |
2843 MacroAssembler _masm(&cbuf); | 2843 MacroAssembler _masm(&cbuf); |
2844 | 2844 |
2845 Register str1_reg = reg_to_register_object($str1$$reg); | 2845 Register str1_reg = reg_to_register_object($str1$$reg); |
2846 Register str2_reg = reg_to_register_object($str2$$reg); | 2846 Register str2_reg = reg_to_register_object($str2$$reg); |
2847 Register tmp1_reg = reg_to_register_object($tmp1$$reg); | 2847 Register cnt1_reg = reg_to_register_object($cnt1$$reg); |
2848 Register tmp2_reg = reg_to_register_object($tmp2$$reg); | 2848 Register cnt2_reg = reg_to_register_object($cnt2$$reg); |
2849 Register result_reg = reg_to_register_object($result$$reg); | 2849 Register result_reg = reg_to_register_object($result$$reg); |
2850 | 2850 |
2851 // Get the first character position in both strings | 2851 assert(result_reg != str1_reg && |
2852 // [8] char array, [12] offset, [16] count | 2852 result_reg != str2_reg && |
2853 int value_offset = java_lang_String:: value_offset_in_bytes(); | 2853 result_reg != cnt1_reg && |
2854 int offset_offset = java_lang_String::offset_offset_in_bytes(); | 2854 result_reg != cnt2_reg , |
2855 int count_offset = java_lang_String:: count_offset_in_bytes(); | 2855 "need different registers"); |
2856 | |
2857 // load str1 (jchar*) base address into tmp1_reg | |
2858 __ load_heap_oop(str1_reg, value_offset, tmp1_reg); | |
2859 __ ld(str1_reg, offset_offset, result_reg); | |
2860 __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); | |
2861 __ ld(str1_reg, count_offset, str1_reg); // hoisted | |
2862 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); | |
2863 __ load_heap_oop(str2_reg, value_offset, tmp2_reg); // hoisted | |
2864 __ add(result_reg, tmp1_reg, tmp1_reg); | |
2865 | |
2866 // load str2 (jchar*) base address into tmp2_reg | |
2867 // __ ld_ptr(str2_reg, value_offset, tmp2_reg); // hoisted | |
2868 __ ld(str2_reg, offset_offset, result_reg); | |
2869 __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg); | |
2870 __ ld(str2_reg, count_offset, str2_reg); // hoisted | |
2871 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); | |
2872 __ subcc(str1_reg, str2_reg, O7); // hoisted | |
2873 __ add(result_reg, tmp2_reg, tmp2_reg); | |
2874 | 2856 |
2875 // Compute the minimum of the string lengths(str1_reg) and the | 2857 // Compute the minimum of the string lengths(str1_reg) and the |
2876 // difference of the string lengths (stack) | 2858 // difference of the string lengths (stack) |
2877 | |
2878 // discard string base pointers, after loading up the lengths | |
2879 // __ ld(str1_reg, count_offset, str1_reg); // hoisted | |
2880 // __ ld(str2_reg, count_offset, str2_reg); // hoisted | |
2881 | 2859 |
2882 // See if the lengths are different, and calculate min in str1_reg. | 2860 // See if the lengths are different, and calculate min in str1_reg. |
2883 // Stash diff in O7 in case we need it for a tie-breaker. | 2861 // Stash diff in O7 in case we need it for a tie-breaker. |
2884 Label Lskip; | 2862 Label Lskip; |
2885 // __ subcc(str1_reg, str2_reg, O7); // hoisted | 2863 __ subcc(cnt1_reg, cnt2_reg, O7); |
2886 __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit | 2864 __ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit |
2887 __ br(Assembler::greater, true, Assembler::pt, Lskip); | 2865 __ br(Assembler::greater, true, Assembler::pt, Lskip); |
2888 // str2 is shorter, so use its count: | 2866 // cnt2 is shorter, so use its count: |
2889 __ delayed()->sll(str2_reg, exact_log2(sizeof(jchar)), str1_reg); // scale the limit | 2867 __ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit |
2890 __ bind(Lskip); | 2868 __ bind(Lskip); |
2891 | 2869 |
2892 // reallocate str1_reg, str2_reg, result_reg | 2870 // reallocate cnt1_reg, cnt2_reg, result_reg |
2893 // Note: limit_reg holds the string length pre-scaled by 2 | 2871 // Note: limit_reg holds the string length pre-scaled by 2 |
2894 Register limit_reg = str1_reg; | 2872 Register limit_reg = cnt1_reg; |
2895 Register chr2_reg = str2_reg; | 2873 Register chr2_reg = cnt2_reg; |
2896 Register chr1_reg = result_reg; | 2874 Register chr1_reg = result_reg; |
2897 // tmp{12} are the base pointers | 2875 // str{12} are the base pointers |
2898 | 2876 |
2899 // Is the minimum length zero? | 2877 // Is the minimum length zero? |
2900 __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity | 2878 __ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity |
2901 __ br(Assembler::equal, true, Assembler::pn, Ldone); | 2879 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
2902 __ delayed()->mov(O7, result_reg); // result is difference in lengths | 2880 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
2903 | 2881 |
2904 // Load first characters | 2882 // Load first characters |
2905 __ lduh(tmp1_reg, 0, chr1_reg); | 2883 __ lduh(str1_reg, 0, chr1_reg); |
2906 __ lduh(tmp2_reg, 0, chr2_reg); | 2884 __ lduh(str2_reg, 0, chr2_reg); |
2907 | 2885 |
2908 // Compare first characters | 2886 // Compare first characters |
2909 __ subcc(chr1_reg, chr2_reg, chr1_reg); | 2887 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
2910 __ br(Assembler::notZero, false, Assembler::pt, Ldone); | 2888 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
2911 assert(chr1_reg == result_reg, "result must be pre-placed"); | 2889 assert(chr1_reg == result_reg, "result must be pre-placed"); |
2913 | 2891 |
2914 { | 2892 { |
2915 // Check after comparing first character to see if strings are equivalent | 2893 // Check after comparing first character to see if strings are equivalent |
2916 Label LSkip2; | 2894 Label LSkip2; |
2917 // Check if the strings start at same location | 2895 // Check if the strings start at same location |
2918 __ cmp(tmp1_reg, tmp2_reg); | 2896 __ cmp(str1_reg, str2_reg); |
2919 __ brx(Assembler::notEqual, true, Assembler::pt, LSkip2); | 2897 __ brx(Assembler::notEqual, true, Assembler::pt, LSkip2); |
2920 __ delayed()->nop(); | 2898 __ delayed()->nop(); |
2921 | 2899 |
2922 // Check if the length difference is zero (in O7) | 2900 // Check if the length difference is zero (in O7) |
2923 __ cmp(G0, O7); | 2901 __ cmp(G0, O7); |
2930 | 2908 |
2931 __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg); | 2909 __ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg); |
2932 __ br(Assembler::equal, true, Assembler::pn, Ldone); | 2910 __ br(Assembler::equal, true, Assembler::pn, Ldone); |
2933 __ delayed()->mov(O7, result_reg); // result is difference in lengths | 2911 __ delayed()->mov(O7, result_reg); // result is difference in lengths |
2934 | 2912 |
2935 // Shift tmp1_reg and tmp2_reg to the end of the arrays, negate limit | 2913 // Shift str1_reg and str2_reg to the end of the arrays, negate limit |
2936 __ add(tmp1_reg, limit_reg, tmp1_reg); | 2914 __ add(str1_reg, limit_reg, str1_reg); |
2937 __ add(tmp2_reg, limit_reg, tmp2_reg); | 2915 __ add(str2_reg, limit_reg, str2_reg); |
2938 __ neg(chr1_reg, limit_reg); // limit = -(limit-2) | 2916 __ neg(chr1_reg, limit_reg); // limit = -(limit-2) |
2939 | 2917 |
2940 // Compare the rest of the characters | 2918 // Compare the rest of the characters |
2941 __ lduh(tmp1_reg, limit_reg, chr1_reg); | 2919 __ lduh(str1_reg, limit_reg, chr1_reg); |
2942 __ bind(Lloop); | 2920 __ bind(Lloop); |
2943 // __ lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted | 2921 // __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
2944 __ lduh(tmp2_reg, limit_reg, chr2_reg); | 2922 __ lduh(str2_reg, limit_reg, chr2_reg); |
2945 __ subcc(chr1_reg, chr2_reg, chr1_reg); | 2923 __ subcc(chr1_reg, chr2_reg, chr1_reg); |
2946 __ br(Assembler::notZero, false, Assembler::pt, Ldone); | 2924 __ br(Assembler::notZero, false, Assembler::pt, Ldone); |
2947 assert(chr1_reg == result_reg, "result must be pre-placed"); | 2925 assert(chr1_reg == result_reg, "result must be pre-placed"); |
2948 __ delayed()->inccc(limit_reg, sizeof(jchar)); | 2926 __ delayed()->inccc(limit_reg, sizeof(jchar)); |
2949 // annul LDUH if branch is not taken to prevent access past end of string | 2927 // annul LDUH if branch is not taken to prevent access past end of string |
2950 __ br(Assembler::notZero, true, Assembler::pt, Lloop); | 2928 __ br(Assembler::notZero, true, Assembler::pt, Lloop); |
2951 __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted | 2929 __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
2952 | 2930 |
2953 // If strings are equal up to min length, return the length difference. | 2931 // If strings are equal up to min length, return the length difference. |
2954 __ mov(O7, result_reg); | 2932 __ mov(O7, result_reg); |
2955 | 2933 |
2956 // Otherwise, return the difference between the first mismatched chars. | 2934 // Otherwise, return the difference between the first mismatched chars. |
2957 __ bind(Ldone); | 2935 __ bind(Ldone); |
2958 %} | 2936 %} |
2959 | 2937 |
2960 enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ | 2938 enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{ |
2961 Label Lword, Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; | 2939 Label Lword_loop, Lpost_word, Lchar, Lchar_loop, Ldone; |
2962 MacroAssembler _masm(&cbuf); | 2940 MacroAssembler _masm(&cbuf); |
2963 | 2941 |
2964 Register str1_reg = reg_to_register_object($str1$$reg); | 2942 Register str1_reg = reg_to_register_object($str1$$reg); |
2965 Register str2_reg = reg_to_register_object($str2$$reg); | 2943 Register str2_reg = reg_to_register_object($str2$$reg); |
2966 Register tmp1_reg = reg_to_register_object($tmp1$$reg); | 2944 Register cnt_reg = reg_to_register_object($cnt$$reg); |
2967 Register tmp2_reg = reg_to_register_object($tmp2$$reg); | 2945 Register tmp1_reg = O7; |
2968 Register result_reg = reg_to_register_object($result$$reg); | 2946 Register result_reg = reg_to_register_object($result$$reg); |
2969 | 2947 |
2970 // Get the first character position in both strings | 2948 assert(result_reg != str1_reg && |
2971 // [8] char array, [12] offset, [16] count | 2949 result_reg != str2_reg && |
2972 int value_offset = java_lang_String:: value_offset_in_bytes(); | 2950 result_reg != cnt_reg && |
2973 int offset_offset = java_lang_String::offset_offset_in_bytes(); | 2951 result_reg != tmp1_reg , |
2974 int count_offset = java_lang_String:: count_offset_in_bytes(); | 2952 "need different registers"); |
2975 | 2953 |
2976 // load str1 (jchar*) base address into tmp1_reg | 2954 __ cmp(str1_reg, str2_reg); //same char[] ? |
2977 __ load_heap_oop(Address(str1_reg, value_offset), tmp1_reg); | |
2978 __ ld(Address(str1_reg, offset_offset), result_reg); | |
2979 __ add(tmp1_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1_reg); | |
2980 __ ld(Address(str1_reg, count_offset), str1_reg); // hoisted | |
2981 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); | |
2982 __ load_heap_oop(Address(str2_reg, value_offset), tmp2_reg); // hoisted | |
2983 __ add(result_reg, tmp1_reg, tmp1_reg); | |
2984 | |
2985 // load str2 (jchar*) base address into tmp2_reg | |
2986 // __ ld_ptr(Address(str2_reg, value_offset), tmp2_reg); // hoisted | |
2987 __ ld(Address(str2_reg, offset_offset), result_reg); | |
2988 __ add(tmp2_reg, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp2_reg); | |
2989 __ ld(Address(str2_reg, count_offset), str2_reg); // hoisted | |
2990 __ sll(result_reg, exact_log2(sizeof(jchar)), result_reg); | |
2991 __ cmp(str1_reg, str2_reg); // hoisted | |
2992 __ add(result_reg, tmp2_reg, tmp2_reg); | |
2993 | |
2994 __ sll(str1_reg, exact_log2(sizeof(jchar)), str1_reg); | |
2995 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); | |
2996 __ delayed()->mov(G0, result_reg); // not equal | |
2997 | |
2998 __ br_zero(Assembler::equal, true, Assembler::pn, str1_reg, Ldone); | |
2999 __ delayed()->add(G0, 1, result_reg); //equals | |
3000 | |
3001 __ cmp(tmp1_reg, tmp2_reg); //same string ? | |
3002 __ brx(Assembler::equal, true, Assembler::pn, Ldone); | 2955 __ brx(Assembler::equal, true, Assembler::pn, Ldone); |
3003 __ delayed()->add(G0, 1, result_reg); | 2956 __ delayed()->add(G0, 1, result_reg); |
3004 | 2957 |
2958 __ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, cnt_reg, Ldone); | |
2959 __ delayed()->add(G0, 1, result_reg); // count == 0 | |
2960 | |
3005 //rename registers | 2961 //rename registers |
3006 Register limit_reg = str1_reg; | 2962 Register limit_reg = cnt_reg; |
3007 Register chr2_reg = str2_reg; | |
3008 Register chr1_reg = result_reg; | 2963 Register chr1_reg = result_reg; |
3009 // tmp{12} are the base pointers | 2964 Register chr2_reg = tmp1_reg; |
3010 | 2965 |
3011 //check for alignment and position the pointers to the ends | 2966 //check for alignment and position the pointers to the ends |
3012 __ or3(tmp1_reg, tmp2_reg, chr1_reg); | 2967 __ or3(str1_reg, str2_reg, chr1_reg); |
3013 __ andcc(chr1_reg, 0x3, chr1_reg); // notZero means at least one not 4-byte aligned | 2968 __ andcc(chr1_reg, 0x3, chr1_reg); |
3014 __ br(Assembler::notZero, false, Assembler::pn, Lchar); | 2969 // notZero means at least one not 4-byte aligned. |
3015 __ delayed()->nop(); | 2970 // We could optimize the case when both arrays are not aligned |
3016 | 2971 // but it is not frequent case and it requires additional checks. |
3017 __ bind(Lword); | 2972 __ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare |
3018 __ and3(limit_reg, 0x2, O7); //remember the remainder (either 0 or 2) | 2973 __ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count |
3019 __ andn(limit_reg, 0x3, limit_reg); | 2974 |
3020 __ br_zero(Assembler::zero, false, Assembler::pn, limit_reg, Lpost_word); | 2975 // Compare char[] arrays aligned to 4 bytes. |
3021 __ delayed()->nop(); | 2976 __ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg, |
3022 | 2977 chr1_reg, chr2_reg, Ldone); |
3023 __ add(tmp1_reg, limit_reg, tmp1_reg); | |
3024 __ add(tmp2_reg, limit_reg, tmp2_reg); | |
3025 __ neg(limit_reg); | |
3026 | |
3027 __ lduw(tmp1_reg, limit_reg, chr1_reg); | |
3028 __ bind(Lword_loop); | |
3029 __ lduw(tmp2_reg, limit_reg, chr2_reg); | |
3030 __ cmp(chr1_reg, chr2_reg); | |
3031 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); | |
3032 __ delayed()->mov(G0, result_reg); | |
3033 __ inccc(limit_reg, 2*sizeof(jchar)); | |
3034 // annul LDUW if branch i s not taken to prevent access past end of string | |
3035 __ br(Assembler::notZero, true, Assembler::pt, Lword_loop); //annul on taken | |
3036 __ delayed()->lduw(tmp1_reg, limit_reg, chr1_reg); // hoisted | |
3037 | |
3038 __ bind(Lpost_word); | |
3039 __ br_zero(Assembler::zero, true, Assembler::pt, O7, Ldone); | |
3040 __ delayed()->add(G0, 1, result_reg); | |
3041 | |
3042 __ lduh(tmp1_reg, 0, chr1_reg); | |
3043 __ lduh(tmp2_reg, 0, chr2_reg); | |
3044 __ cmp (chr1_reg, chr2_reg); | |
3045 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); | |
3046 __ delayed()->mov(G0, result_reg); | |
3047 __ ba(false,Ldone); | 2978 __ ba(false,Ldone); |
3048 __ delayed()->add(G0, 1, result_reg); | 2979 __ delayed()->add(G0, 1, result_reg); |
3049 | 2980 |
2981 // char by char compare | |
3050 __ bind(Lchar); | 2982 __ bind(Lchar); |
3051 __ add(tmp1_reg, limit_reg, tmp1_reg); | 2983 __ add(str1_reg, limit_reg, str1_reg); |
3052 __ add(tmp2_reg, limit_reg, tmp2_reg); | 2984 __ add(str2_reg, limit_reg, str2_reg); |
3053 __ neg(limit_reg); //negate count | 2985 __ neg(limit_reg); //negate count |
3054 | 2986 |
3055 __ lduh(tmp1_reg, limit_reg, chr1_reg); | 2987 __ lduh(str1_reg, limit_reg, chr1_reg); |
2988 // Lchar_loop | |
3056 __ bind(Lchar_loop); | 2989 __ bind(Lchar_loop); |
3057 __ lduh(tmp2_reg, limit_reg, chr2_reg); | 2990 __ lduh(str2_reg, limit_reg, chr2_reg); |
3058 __ cmp(chr1_reg, chr2_reg); | 2991 __ cmp(chr1_reg, chr2_reg); |
3059 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); | 2992 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); |
3060 __ delayed()->mov(G0, result_reg); //not equal | 2993 __ delayed()->mov(G0, result_reg); //not equal |
3061 __ inccc(limit_reg, sizeof(jchar)); | 2994 __ inccc(limit_reg, sizeof(jchar)); |
3062 // annul LDUH if branch is not taken to prevent access past end of string | 2995 // annul LDUH if branch is not taken to prevent access past end of string |
3063 __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); //annul on taken | 2996 __ br(Assembler::notZero, true, Assembler::pt, Lchar_loop); |
3064 __ delayed()->lduh(tmp1_reg, limit_reg, chr1_reg); // hoisted | 2997 __ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted |
3065 | 2998 |
3066 __ add(G0, 1, result_reg); //equal | 2999 __ add(G0, 1, result_reg); //equal |
3067 | 3000 |
3068 __ bind(Ldone); | 3001 __ bind(Ldone); |
3069 %} | 3002 %} |
3070 | 3003 |
3071 enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result) %{ | 3004 enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{ |
3072 Label Lvector, Ldone, Lloop; | 3005 Label Lvector, Ldone, Lloop; |
3073 MacroAssembler _masm(&cbuf); | 3006 MacroAssembler _masm(&cbuf); |
3074 | 3007 |
3075 Register ary1_reg = reg_to_register_object($ary1$$reg); | 3008 Register ary1_reg = reg_to_register_object($ary1$$reg); |
3076 Register ary2_reg = reg_to_register_object($ary2$$reg); | 3009 Register ary2_reg = reg_to_register_object($ary2$$reg); |
3077 Register tmp1_reg = reg_to_register_object($tmp1$$reg); | 3010 Register tmp1_reg = reg_to_register_object($tmp1$$reg); |
3078 Register tmp2_reg = reg_to_register_object($tmp2$$reg); | 3011 Register tmp2_reg = O7; |
3079 Register result_reg = reg_to_register_object($result$$reg); | 3012 Register result_reg = reg_to_register_object($result$$reg); |
3080 | 3013 |
3081 int length_offset = arrayOopDesc::length_offset_in_bytes(); | 3014 int length_offset = arrayOopDesc::length_offset_in_bytes(); |
3082 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); | 3015 int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); |
3083 | 3016 |
3099 // return false if the two arrays are not equal length | 3032 // return false if the two arrays are not equal length |
3100 __ cmp(tmp1_reg, tmp2_reg); | 3033 __ cmp(tmp1_reg, tmp2_reg); |
3101 __ br(Assembler::notEqual, true, Assembler::pn, Ldone); | 3034 __ br(Assembler::notEqual, true, Assembler::pn, Ldone); |
3102 __ delayed()->mov(G0, result_reg); // not equal | 3035 __ delayed()->mov(G0, result_reg); // not equal |
3103 | 3036 |
3104 __ br_zero(Assembler::zero, true, Assembler::pn, tmp1_reg, Ldone); | 3037 __ br_on_reg_cond(Assembler::rc_z, true, Assembler::pn, tmp1_reg, Ldone); |
3105 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal | 3038 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal |
3106 | 3039 |
3107 // load array addresses | 3040 // load array addresses |
3108 __ add(ary1_reg, base_offset, ary1_reg); | 3041 __ add(ary1_reg, base_offset, ary1_reg); |
3109 __ add(ary2_reg, base_offset, ary2_reg); | 3042 __ add(ary2_reg, base_offset, ary2_reg); |
3110 | 3043 |
3111 // renaming registers | 3044 // renaming registers |
3112 Register chr1_reg = tmp2_reg; // for characters in ary1 | 3045 Register chr1_reg = result_reg; // for characters in ary1 |
3113 Register chr2_reg = result_reg; // for characters in ary2 | 3046 Register chr2_reg = tmp2_reg; // for characters in ary2 |
3114 Register limit_reg = tmp1_reg; // length | 3047 Register limit_reg = tmp1_reg; // length |
3115 | 3048 |
3116 // set byte count | 3049 // set byte count |
3117 __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); | 3050 __ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); |
3118 __ andcc(limit_reg, 0x2, chr1_reg); //trailing character ? | 3051 |
3119 __ br(Assembler::zero, false, Assembler::pt, Lvector); | 3052 // Compare char[] arrays aligned to 4 bytes. |
3120 __ delayed()->nop(); | 3053 __ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg, |
3121 | 3054 chr1_reg, chr2_reg, Ldone); |
3122 //compare the trailing char | |
3123 __ sub(limit_reg, sizeof(jchar), limit_reg); | |
3124 __ lduh(ary1_reg, limit_reg, chr1_reg); | |
3125 __ lduh(ary2_reg, limit_reg, chr2_reg); | |
3126 __ cmp(chr1_reg, chr2_reg); | |
3127 __ br(Assembler::notEqual, true, Assembler::pt, Ldone); | |
3128 __ delayed()->mov(G0, result_reg); // not equal | |
3129 | |
3130 // only one char ? | |
3131 __ br_zero(Assembler::zero, true, Assembler::pn, limit_reg, Ldone); | |
3132 __ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal | |
3133 | |
3134 __ bind(Lvector); | |
3135 // Shift ary1_reg and ary2_reg to the end of the arrays, negate limit | |
3136 __ add(ary1_reg, limit_reg, ary1_reg); | |
3137 __ add(ary2_reg, limit_reg, ary2_reg); | |
3138 __ neg(limit_reg, limit_reg); | |
3139 | |
3140 __ lduw(ary1_reg, limit_reg, chr1_reg); | |
3141 __ bind(Lloop); | |
3142 __ lduw(ary2_reg, limit_reg, chr2_reg); | |
3143 __ cmp(chr1_reg, chr2_reg); | |
3144 __ br(Assembler::notEqual, false, Assembler::pt, Ldone); | |
3145 __ delayed()->mov(G0, result_reg); // not equal | |
3146 __ inccc(limit_reg, 2*sizeof(jchar)); | |
3147 // annul LDUW if branch is not taken to prevent access past end of string | |
3148 __ br(Assembler::notZero, true, Assembler::pt, Lloop); //annul on taken | |
3149 __ delayed()->lduw(ary1_reg, limit_reg, chr1_reg); // hoisted | |
3150 | |
3151 __ add(G0, 1, result_reg); // equals | 3055 __ add(G0, 1, result_reg); // equals |
3152 | 3056 |
3153 __ bind(Ldone); | 3057 __ bind(Ldone); |
3154 %} | 3058 %} |
3155 | 3059 |
9469 " STX G0,[$base+$temp]\t! delay slot" %} | 9373 " STX G0,[$base+$temp]\t! delay slot" %} |
9470 ins_encode( enc_Clear_Array(cnt, base, temp) ); | 9374 ins_encode( enc_Clear_Array(cnt, base, temp) ); |
9471 ins_pipe(long_memory_op); | 9375 ins_pipe(long_memory_op); |
9472 %} | 9376 %} |
9473 | 9377 |
9474 instruct string_compare(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, | 9378 instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result, |
9475 o7RegI tmp3, flagsReg ccr) %{ | 9379 o7RegI tmp, flagsReg ccr) %{ |
9476 match(Set result (StrComp str1 str2)); | 9380 match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2))); |
9477 effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); | 9381 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp); |
9478 ins_cost(300); | 9382 ins_cost(300); |
9479 format %{ "String Compare $str1,$str2 -> $result" %} | 9383 format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %} |
9480 ins_encode( enc_String_Compare(str1, str2, tmp1, tmp2, result) ); | 9384 ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) ); |
9481 ins_pipe(long_memory_op); | 9385 ins_pipe(long_memory_op); |
9482 %} | 9386 %} |
9483 | 9387 |
9484 instruct string_equals(o0RegP str1, o1RegP str2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, | 9388 instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result, |
9485 o7RegI tmp3, flagsReg ccr) %{ | 9389 o7RegI tmp, flagsReg ccr) %{ |
9486 match(Set result (StrEquals str1 str2)); | 9390 match(Set result (StrEquals (Binary str1 str2) cnt)); |
9487 effect(USE_KILL str1, USE_KILL str2, KILL tmp1, KILL tmp2, KILL ccr, KILL tmp3); | 9391 effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr); |
9488 ins_cost(300); | 9392 ins_cost(300); |
9489 format %{ "String Equals $str1,$str2 -> $result" %} | 9393 format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} |
9490 ins_encode( enc_String_Equals(str1, str2, tmp1, tmp2, result) ); | 9394 ins_encode( enc_String_Equals(str1, str2, cnt, result) ); |
9491 ins_pipe(long_memory_op); | 9395 ins_pipe(long_memory_op); |
9492 %} | 9396 %} |
9493 | 9397 |
9494 instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, g4RegP tmp2, notemp_iRegI result, | 9398 instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result, |
9495 flagsReg ccr) %{ | 9399 o7RegI tmp2, flagsReg ccr) %{ |
9496 match(Set result (AryEq ary1 ary2)); | 9400 match(Set result (AryEq ary1 ary2)); |
9497 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); | 9401 effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr); |
9498 ins_cost(300); | 9402 ins_cost(300); |
9499 format %{ "Array Equals $ary1,$ary2 -> $result" %} | 9403 format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %} |
9500 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, tmp2, result)); | 9404 ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result)); |
9501 ins_pipe(long_memory_op); | 9405 ins_pipe(long_memory_op); |
9502 %} | 9406 %} |
9503 | 9407 |
9504 | 9408 |
9505 //---------- Zeros Count Instructions ------------------------------------------ | 9409 //---------- Zeros Count Instructions ------------------------------------------ |