1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * Tests for SAD (sum of absolute differences).
19  *
20  * Special case, char array that is first casted to short, forcing sign extension.
21  */
22 public class Main {
23 
24   // TODO: lower precision still coming, b/64091002
25 
sadCastedChar2Short(char[] s1, char[] s2)26   private static short sadCastedChar2Short(char[] s1, char[] s2) {
27     int min_length = Math.min(s1.length, s2.length);
28     short sad = 0;
29     for (int i = 0; i < min_length; i++) {
30       sad += Math.abs(((short) s1[i]) - ((short) s2[i]));
31     }
32     return sad;
33   }
34 
sadCastedChar2ShortAlt(char[] s1, char[] s2)35   private static short sadCastedChar2ShortAlt(char[] s1, char[] s2) {
36     int min_length = Math.min(s1.length, s2.length);
37     short sad = 0;
38     for (int i = 0; i < min_length; i++) {
39       short s = (short) s1[i];
40       short p = (short) s2[i];
41       sad += s >= p ? s - p : p - s;
42     }
43     return sad;
44   }
45 
sadCastedChar2ShortAlt2(char[] s1, char[] s2)46   private static short sadCastedChar2ShortAlt2(char[] s1, char[] s2) {
47     int min_length = Math.min(s1.length, s2.length);
48     short sad = 0;
49     for (int i = 0; i < min_length; i++) {
50       short s = (short) s1[i];
51       short p = (short) s2[i];
52       int x = s - p;
53       if (x < 0) x = -x;
54       sad += x;
55     }
56     return sad;
57   }
58 
59   /// CHECK-START: int Main.sadCastedChar2Int(char[], char[]) instruction_simplifier (before)
60   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
61   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
62   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
63   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
64   /// CHECK-DAG: <<BC1:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
65   /// CHECK-DAG: <<BC2:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
66   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]   loop:<<Loop>>      outer_loop:none
67   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]   loop:<<Loop>>      outer_loop:none
68   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
69   /// CHECK-DAG: <<Cnv2:s\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
70   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
71   /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
72   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
73   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
74   //
75   /// CHECK-START: int Main.sadCastedChar2Int(char[], char[]) loop_optimization (before)
76   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
77   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
78   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
79   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
80   /// CHECK-DAG: <<Get1:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
81   /// CHECK-DAG: <<Get2:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
82   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Get1>>,<<Get2>>]        loop:<<Loop>>      outer_loop:none
83   /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
84   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
85   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
86   //
87   /// CHECK-START-{ARM64,MIPS64}: int Main.sadCastedChar2Int(char[], char[]) loop_optimization (after)
88   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
89   /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
90   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
91   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
92   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
93   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
94   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
95   /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
96   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
sadCastedChar2Int(char[] s1, char[] s2)97   private static int sadCastedChar2Int(char[] s1, char[] s2) {
98     int min_length = Math.min(s1.length, s2.length);
99     int sad = 0;
100     for (int i = 0; i < min_length; i++) {
101       sad += Math.abs(((short) s1[i]) - ((short) s2[i]));
102     }
103     return sad;
104   }
105 
106   /// CHECK-START: int Main.sadCastedChar2IntAlt(char[], char[]) instruction_simplifier (before)
107   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
108   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
109   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
110   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
111   /// CHECK-DAG: <<BC1:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
112   /// CHECK-DAG: <<BC2:i\d+>>    BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
113   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]    loop:<<Loop>>      outer_loop:none
114   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]    loop:<<Loop>>      outer_loop:none
115   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
116   /// CHECK-DAG: <<Cnv2:s\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
117   /// CHECK-DAG: <<Sub1:i\d+>>   Sub [<<Cnv2>>,<<Cnv1>>]        loop:<<Loop>>      outer_loop:none
118   /// CHECK-DAG: <<Sub2:i\d+>>   Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
119   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Sub2>>,<<Sub1>>]        loop:<<Loop>>      outer_loop:none
120   /// CHECK-DAG:                 Add [<<Phi2>>,<<Phi3>>]        loop:<<Loop>>      outer_loop:none
121   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
122   //
123   /// CHECK-START: int Main.sadCastedChar2IntAlt(char[], char[]) loop_optimization (before)
124   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
125   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
126   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
127   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
128   // Note: Get1+Cnv1 not simplified yet due to env use of Get1 in NullCheck for s2[i].
129   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
130   /// CHECK-DAG: <<Get2:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
131   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
132   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Get2>>,<<Cnv1>>]        loop:<<Loop>>      outer_loop:none
133   /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
134   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
135   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
136   //
137   /// CHECK-START-{ARM64,MIPS64}: int Main.sadCastedChar2IntAlt(char[], char[]) loop_optimization (after)
138   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
139   /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
140   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
141   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
142   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
143   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
144   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
145   /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load2>>,<<Load1>>] loop:<<Loop>> outer_loop:none
146   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
sadCastedChar2IntAlt(char[] s1, char[] s2)147   private static int sadCastedChar2IntAlt(char[] s1, char[] s2) {
148     int min_length = Math.min(s1.length, s2.length);
149     int sad = 0;
150     for (int i = 0; i < min_length; i++) {
151       short s = (short) s1[i];
152       short p = (short) s2[i];
153       sad += s >= p ? s - p : p - s;
154     }
155     return sad;
156   }
157 
158   /// CHECK-START: int Main.sadCastedChar2IntAlt2(char[], char[]) instruction_simplifier (before)
159   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
160   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
161   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
162   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
163   /// CHECK-DAG: <<BC1:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
164   /// CHECK-DAG: <<BC2:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
165   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]    loop:<<Loop>>      outer_loop:none
166   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]    loop:<<Loop>>      outer_loop:none
167   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
168   /// CHECK-DAG: <<Cnv2:s\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
169   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
170   /// CHECK-DAG: <<Neg:i\d+>>    Neg [<<Sub>>]                  loop:<<Loop>>      outer_loop:none
171   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Sub>>,<<Neg>>]          loop:<<Loop>>      outer_loop:none
172   /// CHECK-DAG:                 Add [<<Phi2>>,<<Phi3>>]        loop:<<Loop>>      outer_loop:none
173   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
174   //
175   /// CHECK-START: int Main.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (before)
176   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
177   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
178   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
179   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
180   // Note: Get1+Cnv1 not simplified yet due to env use of Get1 in NullCheck for s2[i].
181   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
182   /// CHECK-DAG: <<Get2:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
183   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
184   /// CHECK-DAG: <<Sub:i\d+>>    Sub [<<Cnv1>>,<<Get2>>]        loop:<<Loop>>      outer_loop:none
185   /// CHECK-DAG: <<Intrin:i\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsInt loop:<<Loop>> outer_loop:none
186   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
187   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
188   //
189   /// CHECK-START-{ARM64,MIPS64}: int Main.sadCastedChar2IntAlt2(char[], char[]) loop_optimization (after)
190   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
191   /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
192   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<Cons0>>]      loop:none
193   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
194   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
195   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
196   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
197   /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
198   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
sadCastedChar2IntAlt2(char[] s1, char[] s2)199   private static int sadCastedChar2IntAlt2(char[] s1, char[] s2) {
200     int min_length = Math.min(s1.length, s2.length);
201     int sad = 0;
202     for (int i = 0; i < min_length; i++) {
203       short s = (short) s1[i];
204       short p = (short) s2[i];
205       int x = s - p;
206       if (x < 0) x = -x;
207       sad += x;
208     }
209     return sad;
210   }
211 
212   /// CHECK-START: long Main.sadCastedChar2Long(char[], char[]) instruction_simplifier (before)
213   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
214   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
215   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
216   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
217   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<ConsL>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
218   /// CHECK-DAG: <<BC1:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
219   /// CHECK-DAG: <<BC2:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
220   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]    loop:<<Loop>>      outer_loop:none
221   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]    loop:<<Loop>>      outer_loop:none
222   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
223   /// CHECK-DAG: <<Cnv2:s\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
224   /// CHECK-DAG: <<Cnv3:j\d+>>   TypeConversion [<<Cnv1>>]      loop:<<Loop>>      outer_loop:none
225   /// CHECK-DAG: <<Cnv4:j\d+>>   TypeConversion [<<Cnv2>>]      loop:<<Loop>>      outer_loop:none
226   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv3>>,<<Cnv4>>]        loop:<<Loop>>      outer_loop:none
227   /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
228   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
229   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
230   //
231   /// CHECK-START: long Main.sadCastedChar2Long(char[], char[]) loop_optimization (before)
232   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
233   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
234   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
235   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
236   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<ConsL>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
237   /// CHECK-DAG: <<Get1:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
238   /// CHECK-DAG: <<Get2:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
239   /// CHECK-DAG: <<Cnv1:j\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
240   /// CHECK-DAG: <<Cnv2:j\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
241   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
242   /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
243   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
244   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
245   //
246   /// CHECK-START-{ARM64,MIPS64}: long Main.sadCastedChar2Long(char[], char[]) loop_optimization (after)
247   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
248   /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
249   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 0                 loop:none
250   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
251   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
252   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
253   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
254   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
255   /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
256   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
sadCastedChar2Long(char[] s1, char[] s2)257   private static long sadCastedChar2Long(char[] s1, char[] s2) {
258     int min_length = Math.min(s1.length, s2.length);
259     long sad = 0;
260     for (int i = 0; i < min_length; i++) {
261       long x = (short) s1[i];
262       long y = (short) s2[i];
263       sad += Math.abs(x - y);
264     }
265     return sad;
266   }
267 
268   /// CHECK-START: long Main.sadCastedChar2LongAt1(char[], char[]) instruction_simplifier (before)
269   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
270   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
271   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
272   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
273   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<ConsL>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
274   /// CHECK-DAG: <<BC1:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
275   /// CHECK-DAG: <<BC2:\i\d+>>   BoundsCheck [<<Phi1>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
276   /// CHECK-DAG: <<Get1:c\d+>>   ArrayGet [{{l\d+}},<<BC1>>]    loop:<<Loop>>      outer_loop:none
277   /// CHECK-DAG: <<Get2:c\d+>>   ArrayGet [{{l\d+}},<<BC2>>]    loop:<<Loop>>      outer_loop:none
278   /// CHECK-DAG: <<Cnv1:s\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
279   /// CHECK-DAG: <<Cnv2:s\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
280   /// CHECK-DAG: <<Cnv3:j\d+>>   TypeConversion [<<Cnv1>>]      loop:<<Loop>>      outer_loop:none
281   /// CHECK-DAG: <<Cnv4:j\d+>>   TypeConversion [<<Cnv2>>]      loop:<<Loop>>      outer_loop:none
282   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv3>>,<<Cnv4>>]        loop:<<Loop>>      outer_loop:none
283   /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
284   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
285   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
286   //
287   /// CHECK-START: long Main.sadCastedChar2LongAt1(char[], char[]) loop_optimization (before)
288   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
289   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                  loop:none
290   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
291   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
292   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<ConsL>>,{{j\d+}}]       loop:<<Loop>>      outer_loop:none
293   /// CHECK-DAG: <<Get1:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
294   /// CHECK-DAG: <<Get2:s\d+>>   ArrayGet [{{l\d+}},<<Phi1>>]   loop:<<Loop>>      outer_loop:none
295   /// CHECK-DAG: <<Cnv1:j\d+>>   TypeConversion [<<Get1>>]      loop:<<Loop>>      outer_loop:none
296   /// CHECK-DAG: <<Cnv2:j\d+>>   TypeConversion [<<Get2>>]      loop:<<Loop>>      outer_loop:none
297   /// CHECK-DAG: <<Sub:j\d+>>    Sub [<<Cnv1>>,<<Cnv2>>]        loop:<<Loop>>      outer_loop:none
298   /// CHECK-DAG: <<Intrin:j\d+>> InvokeStaticOrDirect [<<Sub>>] intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none
299   /// CHECK-DAG:                 Add [<<Phi2>>,<<Intrin>>]      loop:<<Loop>>      outer_loop:none
300   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]       loop:<<Loop>>      outer_loop:none
301   //
302   /// CHECK-START-{ARM64,MIPS64}: long Main.sadCastedChar2LongAt1(char[], char[]) loop_optimization (after)
303   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                  loop:none
304   /// CHECK-DAG: <<Cons8:i\d+>>  IntConstant 8                  loop:none
305   /// CHECK-DAG: <<ConsL:j\d+>>  LongConstant 1                 loop:none
306   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [<<ConsL>>]      loop:none
307   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]       loop:<<Loop:B\d+>> outer_loop:none
308   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set>>,{{d\d+}}]         loop:<<Loop>>      outer_loop:none
309   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
310   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<Phi1>>]    loop:<<Loop>>      outer_loop:none
311   /// CHECK-DAG: <<SAD:d\d+>>    VecSADAccumulate [<<Phi2>>,<<Load1>>,<<Load2>>] loop:<<Loop>> outer_loop:none
312   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons8>>]       loop:<<Loop>>      outer_loop:none
sadCastedChar2LongAt1(char[] s1, char[] s2)313   private static long sadCastedChar2LongAt1(char[] s1, char[] s2) {
314     int min_length = Math.min(s1.length, s2.length);
315     long sad = 1;  // starts at 1
316     for (int i = 0; i < min_length; i++) {
317       long x = (short) s1[i];
318       long y = (short) s2[i];
319       sad += Math.abs(x - y);
320     }
321     return sad;
322   }
323 
main(String[] args)324   public static void main(String[] args) {
325     // Cross-test the two most extreme values individually.
326     char[] s1 = { 0, 0x8000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
327     char[] s2 = { 0, 0x7fff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
328     expectEquals(-1, sadCastedChar2Short(s1, s2));
329     expectEquals(-1, sadCastedChar2Short(s2, s1));
330     expectEquals(-1, sadCastedChar2ShortAlt(s1, s2));
331     expectEquals(-1, sadCastedChar2ShortAlt(s2, s1));
332     expectEquals(-1, sadCastedChar2ShortAlt2(s1, s2));
333     expectEquals(-1, sadCastedChar2ShortAlt2(s2, s1));
334     expectEquals(65535, sadCastedChar2Int(s1, s2));
335     expectEquals(65535, sadCastedChar2Int(s2, s1));
336     expectEquals(65535, sadCastedChar2IntAlt(s1, s2));
337     expectEquals(65535, sadCastedChar2IntAlt(s2, s1));
338     expectEquals(65535, sadCastedChar2IntAlt2(s1, s2));
339     expectEquals(65535, sadCastedChar2IntAlt2(s2, s1));
340     expectEquals(65535L, sadCastedChar2Long(s1, s2));
341     expectEquals(65535L, sadCastedChar2Long(s2, s1));
342     expectEquals(65536L, sadCastedChar2LongAt1(s1, s2));
343     expectEquals(65536L, sadCastedChar2LongAt1(s2, s1));
344 
345     // Use cross-values to test all cases.
346     char[] interesting = {
347       (char) 0x0000,
348       (char) 0x0001,
349       (char) 0x0002,
350       (char) 0x1234,
351       (char) 0x8000,
352       (char) 0x8001,
353       (char) 0x7fff,
354       (char) 0xffff
355     };
356     int n = interesting.length;
357     int m = n * n + 1;
358     s1 = new char[m];
359     s2 = new char[m];
360     int k = 0;
361     for (int i = 0; i < n; i++) {
362       for (int j = 0; j < n; j++) {
363         s1[k] = interesting[i];
364         s2[k] = interesting[j];
365         k++;
366       }
367     }
368     s1[k] = 10;
369     s2[k] = 2;
370     expectEquals(-18932, sadCastedChar2Short(s1, s2));
371     expectEquals(-18932, sadCastedChar2ShortAlt(s1, s2));
372     expectEquals(-18932, sadCastedChar2ShortAlt2(s1, s2));
373     expectEquals(1291788, sadCastedChar2Int(s1, s2));
374     expectEquals(1291788, sadCastedChar2IntAlt(s1, s2));
375     expectEquals(1291788, sadCastedChar2IntAlt2(s1, s2));
376     expectEquals(1291788L, sadCastedChar2Long(s1, s2));
377     expectEquals(1291789L, sadCastedChar2LongAt1(s1, s2));
378 
379     System.out.println("passed");
380   }
381 
expectEquals(int expected, int result)382   private static void expectEquals(int expected, int result) {
383     if (expected != result) {
384       throw new Error("Expected: " + expected + ", found: " + result);
385     }
386   }
387 
expectEquals(long expected, long result)388   private static void expectEquals(long expected, long result) {
389     if (expected != result) {
390       throw new Error("Expected: " + expected + ", found: " + result);
391     }
392   }
393 }
394