Home | History | Annotate | Download | only in src
      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
     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
     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
    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
    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
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    323   public static void main(String[] args) {
    324     test1();
    325     test2();
    326     test4();
    327     test5();
    328     test6();
    329     System.out.println("passed");
    330   }
    331 
    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