Skip to content

Commit c8a2849

Browse files
author
Jason Tatton (AWS)
committed
8173585: Intrinsify StringLatin1.indexOf(char)
Rewrite of unit test and newlines added to end of files Changes to unit test: - main test adjusted such that Strings gennerated are much longer (up to 2048 characters) and of the form: azaza, aazaazaa, aaazaaazaaa, etc with 'z' being the search character searched for. Multiple instances of the search character are included in the String in order to validate that the starting offset is correctly handleded. Results are compared to non intrinsified version of the code. Longer strings means that the looping functionality of the various paths is entered into. - Run configurations introduced such that it checks behaviour where use of SSE and AVX instructions are restricted. - Tier4InvocationThreshold adjusted so as to ensure C2 code iis invoked. Other changes: - newlines added at end of files
1 parent c8cc441 commit c8a2849

File tree

3 files changed

+54
-34
lines changed

3 files changed

+54
-34
lines changed

src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1886,7 +1886,7 @@ void C2_MacroAssembler::stringL_indexof_char(Register str1, Register cnt1, Regis
18861886

18871887
bind(SCAN_TO_32_CHAR_LOOP);
18881888
vmovdqu(vec3, Address(result, 0));
1889-
vpcmpeqb(vec3, vec3, vec1, 1);
1889+
vpcmpeqb(vec3, vec3, vec1, Assembler::AVX_256bit);
18901890
vptest(vec2, vec3);
18911891
jcc(Assembler::carryClear, FOUND_CHAR);
18921892
addptr(result, 32);

test/hotspot/jtreg/compiler/intrinsics/string/TestStringLatin1IndexOfChar.java

Lines changed: 52 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,29 @@
44
* @summary Test intrinsification of StringLatin1.indexOf(char). Note that
55
* differing code paths are taken contingent upon the length of the input String.
66
* Hence we must test against differing string lengths in order to validate
7-
* correct functionality
7+
* correct functionality. We also ensure the strings are long enough to trigger
8+
* the looping conditions of the individual code paths.
9+
*
10+
* Run with varing levels of AVX and SSE support, also without the intrinsic at all
811
*
912
* @library /compiler/patches /test/lib
10-
* @run main/othervm -Xbatch -XX:CompileThreshold=100 -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_indexOfL_char compiler.intrinsics.string.TestStringLatin1IndexOfChar
11-
* @run main/othervm -Xbatch -XX:CompileThreshold=100 compiler.intrinsics.string.TestStringLatin1IndexOfChar
13+
* @run main/othervm -Xbatch -XX:Tier4InvocationThreshold=200 -XX:CompileThreshold=100 compiler.intrinsics.string.TestStringLatin1IndexOfChar
14+
* @run main/othervm -Xbatch -XX:Tier4InvocationThreshold=200 -XX:CompileThreshold=100 -XX:+UnlockDiagnosticVMOptions -XX:DisableIntrinsic=_indexOfL_char compiler.intrinsics.string.TestStringLatin1IndexOfChar
15+
* @run main/othervm -Xbatch -XX:Tier4InvocationThreshold=200 -XX:CompileThreshold=100 -XX:UseSSE=0 compiler.intrinsics.string.TestStringLatin1IndexOfChar
16+
* @run main/othervm -Xbatch -XX:Tier4InvocationThreshold=200 -XX:CompileThreshold=100 -XX:UseAVX=1 compiler.intrinsics.string.TestStringLatin1IndexOfChar
17+
* @run main/othervm -Xbatch -XX:Tier4InvocationThreshold=200 -XX:CompileThreshold=100 -XX:UseAVX=2 compiler.intrinsics.string.TestStringLatin1IndexOfChar
18+
* @run main/othervm -Xbatch -XX:Tier4InvocationThreshold=200 -XX:CompileThreshold=100 -XX:UseAVX=3 compiler.intrinsics.string.TestStringLatin1IndexOfChar
1219
*/
1320

1421
package compiler.intrinsics.string;
1522

1623
import jdk.test.lib.Asserts;
17-
import java.util.HashMap;
18-
import java.util.Map;
1924

2025
public class TestStringLatin1IndexOfChar{
21-
private final static int MAX_LENGTH = 513;//future proof for AVX-512 instructions
26+
private final static int MAX_LENGTH = 2048;//future proof for AVX-512 instructions
2227

2328
public static void main(String[] args) throws Exception {
24-
for (int i = 0; i < 100_0; ++i) {//repeat such that we enter into C2 code...
29+
for (int i = 0; i < 1_000; ++i) {//repeat such that we enter into C2 code...
2530
maintest();
2631
testEmpty();
2732
}
@@ -31,46 +36,62 @@ private static void testEmpty(){
3136
Asserts.assertEQ("".indexOf('a'), -1);
3237
}
3338

34-
private static final char[] alphabet = new char[]{'a', 'b', 'c'};//Latin1 are made of these
39+
private final static char SEARCH_CHAR = 'z';
40+
private final static char INVERLEAVING_CHAR = 'a';
41+
private final static char MISSING_CHAR = 'd';
3542

3643
private static void maintest(){
3744
//progressivly move through string checking indexes and starting offset correctly processed
38-
for(int strLength = alphabet.length; strLength < MAX_LENGTH; strLength++){
39-
String totest = makeCandidateStringLatin1(strLength);
45+
//string is of form azaza, aazaazaa, aaazaaazaaa, etc
46+
//we find n s.t. maxlength = (n*3) + 2
47+
int maxaInstances = (MAX_LENGTH-2)/3;
4048

41-
//track starting offset here
42-
Map<Character, Integer> lastIndexOf = new HashMap<Character, Integer>();
43-
for(Character c : alphabet){
44-
lastIndexOf.put(c, 0);
45-
}
49+
for(int aInstances = 5; aInstances < MAX_LENGTH; aInstances++){
50+
String totest = makeCandidateStringLatin1(aInstances);
51+
52+
int startoffset;
53+
{
54+
int intri = totest.indexOf(SEARCH_CHAR);
55+
int nonintri = indexOfCharNonIntrinsic(totest, SEARCH_CHAR, 0);
4656

47-
for(int alphaidx = 0; ; alphaidx++){
48-
char wanted = alphabet[alphaidx % alphabet.length];
49-
int lastInst = lastIndexOf.get(wanted);
57+
Asserts.assertEQ(intri, nonintri);
58+
startoffset = intri+1;
59+
}
5060

51-
int intri = totest.indexOf(wanted, lastInst);
52-
int nonintri = indexOfChar(totest, wanted, lastInst);
61+
{
62+
int intri = totest.indexOf(SEARCH_CHAR, startoffset);
63+
int nonintri = indexOfCharNonIntrinsic(totest, SEARCH_CHAR, startoffset);
5364

5465
Asserts.assertEQ(intri, nonintri);
55-
if(intri == -1 || intri == strLength-1){
56-
break;
57-
}
58-
lastIndexOf.put(wanted, intri+1);
66+
startoffset = intri+1;
5967
}
6068

61-
Asserts.assertEQ(totest.indexOf('d'), -1);
69+
Asserts.assertEQ(totest.indexOf(SEARCH_CHAR, startoffset), -1);//only two SEARCH_CHAR per string
70+
Asserts.assertEQ(totest.indexOf(MISSING_CHAR), -1);
6271
}
6372
}
6473

65-
private static String makeCandidateStringLatin1(int strLength){
66-
StringBuilder sb = new StringBuilder(strLength);
67-
for(int n =0; n < strLength; n++){//only 1 byte elements...
68-
sb.append(alphabet[n % alphabet.length]);
74+
private static String makeCandidateStringLatin1(int aInstances){
75+
StringBuilder sb = new StringBuilder((aInstances*3) + 2);
76+
for(int n =0; n < aInstances; n++){
77+
sb.append(INVERLEAVING_CHAR);
78+
}
79+
80+
sb.append(SEARCH_CHAR);
81+
82+
for(int n =0; n < aInstances; n++){
83+
sb.append(INVERLEAVING_CHAR);
84+
}
85+
86+
sb.append(SEARCH_CHAR);
87+
88+
for(int n =0; n < aInstances; n++){
89+
sb.append(INVERLEAVING_CHAR);
6990
}
7091
return sb.toString();
7192
}
7293

73-
private static int indexOfChar(String value, int ch, int fromIndex) {
94+
private static int indexOfCharNonIntrinsic(String value, int ch, int fromIndex) {
7495
//non intrinsic version of indexOfChar
7596
byte c = (byte)ch;
7697
for (int i = fromIndex; i < value.length(); i++) {
@@ -80,5 +101,4 @@ private static int indexOfChar(String value, int ch, int fromIndex) {
80101
}
81102
return -1;
82103
}
83-
84-
}
104+
}

test/micro/org/openjdk/bench/java/lang/StringIndexOfChar.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,4 +196,4 @@ public static int utf16_AVX2_String() {
196196
}
197197
return ret;
198198
}
199-
}
199+
}

0 commit comments

Comments
 (0)