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 zero vectorization.
19  */
20 public class Main {
21 
22   /// CHECK-START: void Main.staticallyAligned(int[]) loop_optimization (before)
23   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
24   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
25   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<One>>,<<AddI:i\d+>>]          loop:<<Loop:B\d+>> outer_loop:none
26   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<Phi>>]           loop:<<Loop>>      outer_loop:none
27   /// CHECK-DAG: <<Add:i\d+>>   Add [<<Get>>,<<One>>]                loop:<<Loop>>      outer_loop:none
28   /// CHECK-DAG:                ArraySet [<<Par>>,<<Phi>>,<<Add>>]   loop:<<Loop>>      outer_loop:none
29   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
30   //
31   /// CHECK-START-ARM: void Main.staticallyAligned(int[]) loop_optimization (after)
32   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
33   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
34   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
35   /// CHECK-DAG: <<Vl:i\d+>>    IntConstant 2                        loop:none
36   /// CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]         loop:none
37   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<Zero>>,<<AddI:i\d+>>]                            loop:<<Loop:B\d+>> outer_loop:none
38   /// CHECK-DAG: <<Nrm:i\d+>>   Add [<<Phi>>,<<One>>]                                   loop:<<Loop>>      outer_loop:none
39   /// CHECK-DAG: <<Load:d\d+>>  VecLoad [<<Par>>,<<Nrm>>]          alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
40   /// CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Repl>>]                              loop:<<Loop>>      outer_loop:none
41   /// CHECK-DAG:                VecStore [<<Par>>,<<Nrm>>,<<Add>>] alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
42   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<Vl>>]                                    loop:<<Loop>>      outer_loop:none
43   //
44   /// CHECK-NOT:                ArrayGet
45   /// CHECK-NOT:                ArraySet
staticallyAligned(int[] a)46   static void staticallyAligned(int[] a) {
47     // Starts at offset 12 (hidden) + 1 * 4 relative to base alignment.
48     // So no peeling, aligned vector, no cleanup.
49     for (int i = 1; i < 9; i++) {
50       a[i] += 1;
51     }
52   }
53 
54   /// CHECK-START: void Main.staticallyAlignedN(int[]) loop_optimization (before)
55   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
56   /// CHECK-DAG: <<Par:l\d+>>   NullCheck                            loop:none
57   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<One>>,<<AddI:i\d+>>]          loop:<<Loop:B\d+>> outer_loop:none
58   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<Phi>>]           loop:<<Loop>>      outer_loop:none
59   /// CHECK-DAG: <<Add:i\d+>>   Add [<<Get>>,<<One>>]                loop:<<Loop>>      outer_loop:none
60   /// CHECK-DAG:                ArraySet [<<Par>>,<<Phi>>,<<Add>>]   loop:<<Loop>>      outer_loop:none
61   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
62   //
63   /// CHECK-START-ARM: void Main.staticallyAlignedN(int[]) loop_optimization (after)
64   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
65   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
66   /// CHECK-DAG: <<Vl:i\d+>>    IntConstant 2                        loop:none
67   /// CHECK-DAG: <<Par:l\d+>>   NullCheck                            loop:none
68   /// CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]         loop:none
69   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<Zero>>,<<AddI:i\d+>>]                            loop:<<Loop:B\d+>> outer_loop:none
70   /// CHECK-DAG: <<Nrm:i\d+>>   Add [<<Phi>>,<<One>>]                                   loop:<<Loop>>      outer_loop:none
71   /// CHECK-DAG: <<Load:d\d+>>  VecLoad [<<Par>>,<<Nrm>>]          alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
72   /// CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Repl>>]                              loop:<<Loop>>      outer_loop:none
73   /// CHECK-DAG:                VecStore [<<Par>>,<<Nrm>>,<<Add>>] alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
74   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<Vl>>]                                    loop:<<Loop>>      outer_loop:none
75   /// CHECK-DAG: <<PhiC:i\d+>>  Phi [<<Phi>>,<<AddIC:i\d+>>]         loop:<<Clean:B\d+>> outer_loop:none
76   /// CHECK-DAG: <<NrmC:i\d+>>  Add [<<PhiC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
77   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<NrmC>>]          loop:<<Clean>>      outer_loop:none
78   /// CHECK-DAG: <<AddC:i\d+>>  Add [<<Get>>,<<One>>]                loop:<<Clean>>      outer_loop:none
79   /// CHECK-DAG:                ArraySet [<<Par>>,<<NrmC>>,<<AddC>>] loop:<<Clean>>      outer_loop:none
80   /// CHECK-DAG: <<AddIC>>      Add [<<PhiC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
staticallyAlignedN(int[] a)81   static void staticallyAlignedN(int[] a) {
82     // Starts at offset 12 (hidden) + 1 * 4 relative to base alignment.
83     // So no peeling, aligned vector, cleanup.
84     for (int i = 1; i < a.length; i++) {
85       a[i] += 1;
86     }
87   }
88 
89   /// CHECK-START: void Main.staticallyMisaligned(int[]) loop_optimization (before)
90   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
91   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
92   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
93   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<Zero>>,<<AddI:i\d+>>]         loop:<<Loop:B\d+>> outer_loop:none
94   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<Phi>>]           loop:<<Loop>>      outer_loop:none
95   /// CHECK-DAG: <<Add:i\d+>>   Add [<<Get>>,<<One>>]                loop:<<Loop>>      outer_loop:none
96   /// CHECK-DAG:                ArraySet [<<Par>>,<<Phi>>,<<Add>>]   loop:<<Loop>>      outer_loop:none
97   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
98   //
99   /// CHECK-START-ARM: void Main.staticallyMisaligned(int[]) loop_optimization (after)
100   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
101   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
102   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
103   /// CHECK-DAG: <<Vl:i\d+>>    IntConstant 2                        loop:none
104   /// CHECK-DAG: <<PhiP:i\d+>>  Phi [<<Zero>>,<<AddIP:i\d+>>]        loop:<<Peel:B\d+>> outer_loop:none
105   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<PhiP>>]          loop:<<Peel>>      outer_loop:none
106   /// CHECK-DAG: <<AddP:i\d+>>  Add [<<Get>>,<<One>>]                loop:<<Peel>>      outer_loop:none
107   /// CHECK-DAG:                ArraySet [<<Par>>,<<PhiP>>,<<AddP>>] loop:<<Peel>>      outer_loop:none
108   /// CHECK-DAG: <<AddIP>>      Add [<<PhiP>>,<<One>>]               loop:<<Peel>>      outer_loop:none
109   /// CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]         loop:none
110   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<PhiP>>,<<AddI:i\d+>>]                            loop:<<Loop:B\d+>> outer_loop:none
111   /// CHECK-DAG: <<Load:d\d+>>  VecLoad [<<Par>>,<<Phi>>]          alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
112   /// CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Repl>>]                              loop:<<Loop>>      outer_loop:none
113   /// CHECK-DAG:                VecStore [<<Par>>,<<Phi>>,<<Add>>] alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
114   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<Vl>>]                                    loop:<<Loop>>      outer_loop:none
115   //
116   /// CHECK-NOT:                ArrayGet
117   /// CHECK-NOT:                ArraySet
staticallyMisaligned(int[] a)118   static void staticallyMisaligned(int[] a) {
119     // Starts at offset 12 (hidden) + 0 * 4 relative to base alignment.
120     // Yes, Art runtime misaligns the most common access pattern :-(
121     // Static peeling to the rescue, aligned vector, no cleanup.
122     for (int i = 0; i < 9; i++) {
123       a[i] += 1;
124     }
125   }
126 
127   /// CHECK-START: void Main.staticallyMisalignedN(int[]) loop_optimization (before)
128   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                       loop:none
129   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                       loop:none
130   /// CHECK-DAG: <<Par:l\d+>>   NullCheck                           loop:none
131   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<Zero>>,<<AddI:i\d+>>]        loop:<<Loop:B\d+>> outer_loop:none
132   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<Phi>>]          loop:<<Loop>>      outer_loop:none
133   /// CHECK-DAG: <<Add:i\d+>>   Add [<<Get>>,<<One>>]               loop:<<Loop>>      outer_loop:none
134   /// CHECK-DAG:                ArraySet [<<Par>>,<<Phi>>,<<Add>>]  loop:<<Loop>>      outer_loop:none
135   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]               loop:<<Loop>>      outer_loop:none
136   //
137   /// CHECK-START-ARM: void Main.staticallyMisalignedN(int[]) loop_optimization (after)
138   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
139   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
140   /// CHECK-DAG: <<Vl:i\d+>>    IntConstant 2                        loop:none
141   /// CHECK-DAG: <<Par:l\d+>>   NullCheck                            loop:none
142   /// CHECK-DAG: <<PhiP:i\d+>>  Phi [<<Zero>>,<<AddIP:i\d+>>]        loop:<<Peel:B\d+>> outer_loop:none
143   /// CHECK-DAG: <<GetP:i\d+>>  ArrayGet [<<Par>>,<<PhiP>>]          loop:<<Peel>>      outer_loop:none
144   /// CHECK-DAG: <<AddP:i\d+>>  Add [<<GetP>>,<<One>>]               loop:<<Peel>>      outer_loop:none
145   /// CHECK-DAG:                ArraySet [<<Par>>,<<PhiP>>,<<AddP>>] loop:<<Peel>>      outer_loop:none
146   /// CHECK-DAG: <<AddIP>>      Add [<<PhiP>>,<<One>>]               loop:<<Peel>>      outer_loop:none
147   /// CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]         loop:none
148   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<PhiP>>,<<AddI:i\d+>>]                            loop:<<Loop:B\d+>> outer_loop:none
149   /// CHECK-DAG: <<Load:d\d+>>  VecLoad [<<Par>>,<<Phi>>]          alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
150   /// CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Repl>>]                              loop:<<Loop>>      outer_loop:none
151   /// CHECK-DAG:                VecStore [<<Par>>,<<Phi>>,<<Add>>] alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
152   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<Vl>>]                                    loop:<<Loop>>      outer_loop:none
153   /// CHECK-DAG: <<PhiC:i\d+>>  Phi [<<Phi>>,<<AddIC:i\d+>>]         loop:<<Clean:B\d+>> outer_loop:none
154   /// CHECK-DAG: <<GetC:i\d+>>  ArrayGet [<<Par>>,<<PhiC>>]          loop:<<Clean>>      outer_loop:none
155   /// CHECK-DAG: <<AddC:i\d+>>  Add [<<GetC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
156   /// CHECK-DAG:                ArraySet [<<Par>>,<<PhiC>>,<<AddC>>] loop:<<Clean>>      outer_loop:none
157   /// CHECK-DAG: <<AddIC>>      Add [<<PhiC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
staticallyMisalignedN(int[] a)158   static void staticallyMisalignedN(int[] a) {
159     // Starts at offset 12 (hidden) + 0 * 4 relative to base alignment.
160     // Yes, Art runtime misaligns the most common access pattern :-(
161     // Static peeling to the rescue, aligned vector, cleanup.
162     for (int i = 0; i < a.length; i++) {
163       a[i] += 1;
164     }
165   }
166 
167   /// CHECK-START: void Main.staticallyUnknownAligned(int[], int) loop_optimization (before)
168   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
169   /// CHECK-DAG: <<Off:i\d+>>   ParameterValue                       loop:none
170   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
171   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
172   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<Zero>>,<<AddI:i\d+>>]         loop:<<Loop:B\d+>> outer_loop:none
173   /// CHECK-DAG: <<Nrm:i\d+>>   Add [<<Off>>,<<Phi>>]                loop:<<Loop>>      outer_loop:none
174   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<Nrm>>]           loop:<<Loop>>      outer_loop:none
175   /// CHECK-DAG: <<Add:i\d+>>   Add [<<Get>>,<<One>>]                loop:<<Loop>>      outer_loop:none
176   /// CHECK-DAG:                ArraySet [<<Par>>,<<Nrm>>,<<Add>>]   loop:<<Loop>>      outer_loop:none
177   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
178   //
179   /// CHECK-START-ARM: void Main.staticallyUnknownAligned(int[], int) loop_optimization (after)
180   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
181   /// CHECK-DAG: <<Off:i\d+>>   ParameterValue                       loop:none
182   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
183   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
184   /// CHECK-DAG: <<Vl:i\d+>>    IntConstant 2                        loop:none
185   /// CHECK-DAG: <<PhiP:i\d+>>  Phi [<<Zero>>,<<AddIP:i\d+>>]        loop:<<Peel:B\d+>> outer_loop:none
186   /// CHECK-DAG: <<NrmP:i\d+>>  Add [<<PhiP>>,<<Off>>]               loop:<<Peel>>      outer_loop:none
187   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<NrmP>>]          loop:<<Peel>>      outer_loop:none
188   /// CHECK-DAG: <<AddP:i\d+>>  Add [<<Get>>,<<One>>]                loop:<<Peel>>      outer_loop:none
189   /// CHECK-DAG:                ArraySet [<<Par>>,<<NrmP>>,<<AddP>>] loop:<<Peel>>      outer_loop:none
190   /// CHECK-DAG: <<AddIP>>      Add [<<PhiP>>,<<One>>]               loop:<<Peel>>      outer_loop:none
191   /// CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]         loop:none
192   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<PhiP>>,<<AddI:i\d+>>]                            loop:<<Loop:B\d+>> outer_loop:none
193   /// CHECK-DAG: <<Nrm:i\d+>>   Add [<<Phi>>,<<Off>>]                                   loop:<<Loop>>      outer_loop:none
194   /// CHECK-DAG: <<Load:d\d+>>  VecLoad [<<Par>>,<<Nrm>>]          alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
195   /// CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Repl>>]                              loop:<<Loop>>      outer_loop:none
196   /// CHECK-DAG:                VecStore [<<Par>>,<<Nrm>>,<<Add>>] alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
197   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<Vl>>]                                    loop:<<Loop>>      outer_loop:none
198   /// CHECK-DAG: <<PhiC:i\d+>>  Phi [<<Phi>>,<<AddIC:i\d+>>]         loop:<<Clean:B\d+>> outer_loop:none
199   /// CHECK-DAG: <<NrmC:i\d+>>  Add [<<PhiC>>,<<Off>>]               loop:<<Clean>>      outer_loop:none
200   /// CHECK-DAG: <<GetC:i\d+>>  ArrayGet [<<Par>>,<<NrmC>>]          loop:<<Clean>>      outer_loop:none
201   /// CHECK-DAG: <<AddC:i\d+>>  Add [<<GetC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
202   /// CHECK-DAG:                ArraySet [<<Par>>,<<NrmC>>,<<AddC>>] loop:<<Clean>>      outer_loop:none
203   /// CHECK-DAG: <<AddIC>>      Add [<<PhiC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
staticallyUnknownAligned(int[] a, int off)204   static void staticallyUnknownAligned(int[] a, int off) {
205     // Starts at an unknown offset due to parameter off.
206     // Dynamic peeling to the rescue, aligned vector, cleanup.
207     for (int i = 0; i < 9; i++) {
208       a[off + i] += 1;
209     }
210   }
211 
212   /// CHECK-START: void Main.staticallyUnknownAlignedN(int[], int, int) loop_optimization (before)
213   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
214   /// CHECK-DAG: <<Off:i\d+>>   ParameterValue                       loop:none
215   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
216   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
217   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<Zero>>,<<AddI:i\d+>>]         loop:<<Loop:B\d+>> outer_loop:none
218   /// CHECK-DAG: <<Nrm:i\d+>>   Add [<<Off>>,<<Phi>>]                loop:<<Loop>>      outer_loop:none
219   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<Nrm>>]           loop:<<Loop>>      outer_loop:none
220   /// CHECK-DAG: <<Add:i\d+>>   Add [<<Get>>,<<One>>]                loop:<<Loop>>      outer_loop:none
221   /// CHECK-DAG:                ArraySet [<<Par>>,<<Nrm>>,<<Add>>]   loop:<<Loop>>      outer_loop:none
222   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
223   //
224   /// CHECK-START-ARM: void Main.staticallyUnknownAlignedN(int[], int, int) loop_optimization (after)
225   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
226   /// CHECK-DAG: <<Off:i\d+>>   ParameterValue                       loop:none
227   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0                        loop:none
228   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
229   /// CHECK-DAG: <<Vl:i\d+>>    IntConstant 2                        loop:none
230   /// CHECK-DAG: <<PhiP:i\d+>>  Phi [<<Zero>>,<<AddIP:i\d+>>]        loop:<<Peel:B\d+>> outer_loop:none
231   /// CHECK-DAG: <<NrmP:i\d+>>  Add [<<PhiP>>,<<Off>>]               loop:<<Peel>>      outer_loop:none
232   /// CHECK-DAG: <<Get:i\d+>>   ArrayGet [<<Par>>,<<NrmP>>]          loop:<<Peel>>      outer_loop:none
233   /// CHECK-DAG: <<AddP:i\d+>>  Add [<<Get>>,<<One>>]                loop:<<Peel>>      outer_loop:none
234   /// CHECK-DAG:                ArraySet [<<Par>>,<<NrmP>>,<<AddP>>] loop:<<Peel>>      outer_loop:none
235   /// CHECK-DAG: <<AddIP>>      Add [<<PhiP>>,<<One>>]               loop:<<Peel>>      outer_loop:none
236   /// CHECK-DAG: <<Repl:d\d+>>  VecReplicateScalar [<<One>>]         loop:none
237   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<PhiP>>,<<AddI:i\d+>>]                            loop:<<Loop:B\d+>> outer_loop:none
238   /// CHECK-DAG: <<Nrm:i\d+>>   Add [<<Phi>>,<<Off>>]                                   loop:<<Loop>>      outer_loop:none
239   /// CHECK-DAG: <<Load:d\d+>>  VecLoad [<<Par>>,<<Nrm>>]          alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
240   /// CHECK-DAG: <<Add:d\d+>>   VecAdd [<<Load>>,<<Repl>>]                              loop:<<Loop>>      outer_loop:none
241   /// CHECK-DAG:                VecStore [<<Par>>,<<Nrm>>,<<Add>>] alignment:ALIGN(8,0) loop:<<Loop>>      outer_loop:none
242   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<Vl>>]                                    loop:<<Loop>>      outer_loop:none
243   /// CHECK-DAG: <<PhiC:i\d+>>  Phi [<<Phi>>,<<AddIC:i\d+>>]         loop:<<Clean:B\d+>> outer_loop:none
244   /// CHECK-DAG: <<NrmC:i\d+>>  Add [<<PhiC>>,<<Off>>]               loop:<<Clean>>      outer_loop:none
245   /// CHECK-DAG: <<GetC:i\d+>>  ArrayGet [<<Par>>,<<NrmC>>]          loop:<<Clean>>      outer_loop:none
246   /// CHECK-DAG: <<AddC:i\d+>>  Add [<<GetC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
247   /// CHECK-DAG:                ArraySet [<<Par>>,<<NrmC>>,<<AddC>>] loop:<<Clean>>      outer_loop:none
248   /// CHECK-DAG: <<AddIC>>      Add [<<PhiC>>,<<One>>]               loop:<<Clean>>      outer_loop:none
staticallyUnknownAlignedN(int[] a, int off, int n)249   static void staticallyUnknownAlignedN(int[] a, int off, int n) {
250     // Starts at an unknown offset due to parameter off.
251     // Dynamic peeling to the rescue, aligned vector, cleanup.
252     for (int i = 0; i < n; i++) {
253       a[off + i] += 1;
254     }
255   }
256 
257   //
258   // Test drivers.
259   //
260 
test1()261   private static void test1() {
262     int[] a = new int[9];
263     staticallyAligned(a);
264     for (int i = 0; i < a.length; i++) {
265       int e = i > 0 ? 1 : 0;
266       expectEquals(e, a[i]);
267     }
268   }
269 
test2()270   private static void test2() {
271     for (int n = 0; n <= 71; n++) {
272       int[] a = new int[n];
273       staticallyAlignedN(a);
274       for (int i = 0; i < a.length; i++) {
275         int e = i > 0 ? 1 : 0;
276         expectEquals(e, a[i]);
277       }
278     }
279   }
280 
test3()281   private static void test3() {
282     int[] a = new int[9];
283     staticallyMisaligned(a);
284     for (int i = 0; i < a.length; i++) {
285       expectEquals(1, a[i]);
286     }
287   }
288 
test4()289   private static void test4() {
290     for (int n = 0; n <= 71; n++) {
291       int[] a = new int[n];
292       staticallyMisalignedN(a);
293       for (int i = 0; i < a.length; i++) {
294         expectEquals(1, a[i]);
295       }
296     }
297   }
298 
test5()299   private static void test5() {
300     for (int off = 0; off <= 8; off++) {
301       int[] a = new int[17];
302       staticallyUnknownAligned(a, off);
303       for (int i = 0; i < a.length; i++) {
304         int e = (off <= i && i < off + 9) ? 1 : 0;
305         expectEquals(e, a[i]);
306       }
307     }
308   }
309 
test6()310   private static void test6() {
311     for (int off = 0; off <= 8; off++) {
312       for (int n = 0; n <= 9; n++) {
313         int[] a = new int[17];
314         staticallyUnknownAlignedN(a, off, n);
315         for (int i = 0; i < a.length; i++) {
316           int e = (off <= i && i < off + n) ? 1 : 0;
317           expectEquals(e, a[i]);
318         }
319       }
320     }
321   }
322 
main(String[] args)323   public static void main(String[] args) {
324     test1();
325     test2();
326     test4();
327     test5();
328     test6();
329     System.out.println("passed");
330   }
331 
expectEquals(int expected, int result)332   private static void expectEquals(int expected, int result) {
333     if (expected != result) {
334       throw new Error("Expected: " + expected + ", found: " + result);
335     }
336   }
337 }
338