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 halving-add idiomatic vectorization.
     19  */
     20 public class Main {
     21 
     22   private static final int N = 64 * 1024;
     23   private static final int M = N + 31;
     24 
     25   static short[] sB1 = new short[M];
     26   static short[] sB2 = new short[M];
     27   static short[] sBo = new short[M];
     28 
     29   /// CHECK-START: void Main.halving_add_signed(short[], short[], short[]) loop_optimization (before)
     30   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
     31   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
     32   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     33   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     34   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
     35   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
     36   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
     37   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
     38   //
     39   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_signed(short[], short[], short[]) loop_optimization (after)
     40   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
     41   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
     42   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
     43   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
     44   private static void halving_add_signed(short[] b1, short[] b2, short[] bo) {
     45     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     46     for (int i = 0; i < min_length; i++) {
     47       bo[i] = (short) ((b1[i] + b2[i]) >> 1);
     48     }
     49   }
     50 
     51   /// CHECK-START: void Main.halving_add_signed_alt(short[], short[], short[]) loop_optimization (before)
     52   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
     53   /// CHECK-DAG: <<I10:i\d+>>  IntConstant 10                      loop:none
     54   /// CHECK-DAG: <<M10:i\d+>>  IntConstant -10                     loop:none
     55   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
     56   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     57   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     58   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<I10>>]              loop:<<Loop>>      outer_loop:none
     59   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Get2>>,<<M10>>]              loop:<<Loop>>      outer_loop:none
     60   /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>]             loop:<<Loop>>      outer_loop:none
     61   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add3>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
     62   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
     63   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
     64   //
     65   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
     66   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
     67   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
     68   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
     69   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
     70   private static void halving_add_signed_alt(short[] b1, short[] b2, short[] bo) {
     71     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
     72     for (int i = 0; i < min_length; i++) {
     73       // Cancelling constant computations do not confuse recognition.
     74       bo[i] = (short) (((b1[i] + 10) + (b2[i] - 10)) >> 1);
     75     }
     76   }
     77 
     78   /// CHECK-START: void Main.halving_add_unsigned(short[], short[], short[]) instruction_simplifier (before)
     79   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
     80   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
     81   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
     82   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     83   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     84   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
     85   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
     86   /// CHECK-DAG: <<Add:i\d+>>  Add [<<And1>>,<<And2>>]             loop:<<Loop>>      outer_loop:none
     87   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
     88   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
     89   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
     90   //
     91   /// CHECK-START: void Main.halving_add_unsigned(short[], short[], short[]) loop_optimization (before)
     92   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
     93   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
     94   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     95   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
     96   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
     97   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
     98   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
     99   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    100   //
    101   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
    102   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    103   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
    104   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
    105   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    106   private static void halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
    107     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
    108     for (int i = 0; i < min_length; i++) {
    109       bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff)) >> 1);
    110     }
    111   }
    112 
    113   /// CHECK-START: void Main.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (before)
    114   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    115   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    116   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    117   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    118   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
    119   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    120   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    121   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    122   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    123   //
    124   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_signed(short[], short[], short[]) loop_optimization (after)
    125   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    126   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
    127   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
    128   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    129   private static void rounding_halving_add_signed(short[] b1, short[] b2, short[] bo) {
    130     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
    131     for (int i = 0; i < min_length; i++) {
    132       bo[i] = (short) ((b1[i] + b2[i] + 1) >> 1);
    133     }
    134   }
    135 
    136   /// CHECK-START: void Main.rounding_halving_add_signed_alt(short[], short[], short[]) loop_optimization (before)
    137   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    138   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    139   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    140   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    141   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    142   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
    143   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    144   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    145   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    146   //
    147   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_signed_alt(short[], short[], short[]) loop_optimization (after)
    148   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    149   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
    150   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
    151   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    152   private static void rounding_halving_add_signed_alt(short[] b1, short[] b2, short[] bo) {
    153     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
    154     for (int i = 0; i < min_length; i++) {
    155       // Slightly different order in idiom does not confuse recognition.
    156       bo[i] = (short) (((1 + b1[i]) + b2[i]) >> 1);
    157     }
    158   }
    159 
    160   /// CHECK-START: void Main.rounding_halving_add_signed_alt2(short[], short[], short[]) loop_optimization (before)
    161   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    162   /// CHECK-DAG: <<I10:i\d+>>  IntConstant 10                      loop:none
    163   /// CHECK-DAG: <<M9:i\d+>>   IntConstant -9                      loop:none
    164   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    165   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    166   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    167   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<I10>>]              loop:<<Loop>>      outer_loop:none
    168   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Get2>>,<<M9>>]               loop:<<Loop>>      outer_loop:none
    169   /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add1>>,<<Add2>>]             loop:<<Loop>>      outer_loop:none
    170   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add3>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    171   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    172   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    173   //
    174   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_signed_alt2(short[], short[], short[]) loop_optimization (after)
    175   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    176   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
    177   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Int16 rounded:true loop:<<Loop>> outer_loop:none
    178   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    179   private static void rounding_halving_add_signed_alt2(short[] b1, short[] b2, short[] bo) {
    180     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
    181     for (int i = 0; i < min_length; i++) {
    182       // Computations that cancel to adding 1 also do not confuse recognition.
    183       bo[i] = (short) (((b1[i] + 10) + (b2[i] - 9)) >> 1);
    184     }
    185   }
    186 
    187   /// CHECK-START: void Main.rounding_halving_add_unsigned(short[], short[], short[]) instruction_simplifier (before)
    188   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    189   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
    190   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    191   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    192   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    193   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
    194   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
    195   /// CHECK-DAG: <<Add1:i\d+>> Add [<<And1>>,<<And2>>]             loop:<<Loop>>      outer_loop:none
    196   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    197   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    198   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    199   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
    200   //
    201   /// CHECK-START: void Main.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (before)
    202   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    203   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    204   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    205   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    206   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get1>>,<<Get2>>]             loop:<<Loop>>      outer_loop:none
    207   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    208   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    209   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    210   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    211   //
    212   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_unsigned(short[], short[], short[]) loop_optimization (after)
    213   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    214   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
    215   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
    216   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    217   private static void rounding_halving_add_unsigned(short[] b1, short[] b2, short[] bo) {
    218     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
    219     for (int i = 0; i < min_length; i++) {
    220       bo[i] = (short) (((b1[i] & 0xffff) + (b2[i] & 0xffff) + 1) >> 1);
    221     }
    222   }
    223 
    224   /// CHECK-START: void Main.rounding_halving_add_unsigned_alt(short[], short[], short[]) instruction_simplifier (before)
    225   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    226   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
    227   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    228   /// CHECK-DAG: <<Get1:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    229   /// CHECK-DAG: <<Get2:s\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    230   /// CHECK-DAG: <<And1:i\d+>> And [<<Get1>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
    231   /// CHECK-DAG: <<And2:i\d+>> And [<<Get2>>,<<UMAX>>]             loop:<<Loop>>      outer_loop:none
    232   /// CHECK-DAG: <<Add1:i\d+>> Add [<<And2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    233   /// CHECK-DAG: <<Add2:i\d+>> Add [<<And1>>,<<Add1>>]             loop:<<Loop>>      outer_loop:none
    234   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    235   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    236   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
    237   //
    238   /// CHECK-START: void Main.rounding_halving_add_unsigned_alt(short[], short[], short[]) loop_optimization (before)
    239   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    240   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    241   /// CHECK-DAG: <<Get1:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    242   /// CHECK-DAG: <<Get2:c\d+>> ArrayGet                            loop:<<Loop>>      outer_loop:none
    243   /// CHECK-DAG: <<Add1:i\d+>> Add [<<Get2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    244   /// CHECK-DAG: <<Add2:i\d+>> Add [<<Get1>>,<<Add1>>]             loop:<<Loop>>      outer_loop:none
    245   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add2>>,<<I1>>]               loop:<<Loop>>      outer_loop:none
    246   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    247   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    248   //
    249   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.rounding_halving_add_unsigned_alt(short[], short[], short[]) loop_optimization (after)
    250   /// CHECK-DAG: <<Get1:d\d+>> VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    251   /// CHECK-DAG: <<Get2:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
    252   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get1>>,<<Get2>>] packed_type:Uint16 rounded:true loop:<<Loop>> outer_loop:none
    253   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    254   private static void rounding_halving_add_unsigned_alt(short[] b1, short[] b2, short[] bo) {
    255     int min_length = Math.min(bo.length, Math.min(b1.length, b2.length));
    256     for (int i = 0; i < min_length; i++) {
    257       // Slightly different order in idiom does not confuse recognition.
    258       bo[i] = (short) ((b1[i] & 0xffff) + ((b2[i] & 0xffff) + 1) >> 1);
    259     }
    260   }
    261 
    262   /// CHECK-START: void Main.halving_add_signed_constant(short[], short[]) loop_optimization (before)
    263   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    264   /// CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                   loop:none
    265   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    266   /// CHECK-DAG: <<Get:s\d+>>  ArrayGet                            loop:<<Loop>>      outer_loop:none
    267   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<SMAX>>]              loop:<<Loop>>      outer_loop:none
    268   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
    269   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    270   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    271   //
    272   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_signed_constant(short[], short[]) loop_optimization (after)
    273   /// CHECK-DAG: <<SMAX:i\d+>> IntConstant 32767                     loop:none
    274   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<SMAX>>]         loop:none
    275   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    276   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Int16 rounded:false loop:<<Loop>> outer_loop:none
    277   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    278   private static void halving_add_signed_constant(short[] b1, short[] bo) {
    279     int min_length = Math.min(bo.length, b1.length);
    280     for (int i = 0; i < min_length; i++) {
    281       bo[i] = (short) ((b1[i] + 0x7fff) >> 1);
    282     }
    283   }
    284 
    285   /// CHECK-START: void Main.halving_add_unsigned_constant(short[], short[]) instruction_simplifier (before)
    286   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    287   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
    288   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    289   /// CHECK-DAG: <<Get:s\d+>>  ArrayGet                            loop:<<Loop>>      outer_loop:none
    290   /// CHECK-DAG: <<And:i\d+>>  And [<<Get>>,<<UMAX>>]              loop:<<Loop>>      outer_loop:none
    291   /// CHECK-DAG: <<Add:i\d+>>  Add [<<And>>,<<UMAX>>]              loop:<<Loop>>      outer_loop:none
    292   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
    293   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    294   /// CHECK-DAG:               ArraySet [{{l\d+}},{{i\d+}},<<Cnv>>] loop:<<Loop>>      outer_loop:none
    295   //
    296   /// CHECK-START: void Main.halving_add_unsigned_constant(short[], short[]) loop_optimization (before)
    297   /// CHECK-DAG: <<I1:i\d+>>   IntConstant 1                       loop:none
    298   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                   loop:none
    299   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
    300   /// CHECK-DAG: <<Get:c\d+>>  ArrayGet                            loop:<<Loop>>      outer_loop:none
    301   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<UMAX>>]              loop:<<Loop>>      outer_loop:none
    302   /// CHECK-DAG: <<Shr:i\d+>>  Shr [<<Add>>,<<I1>>]                loop:<<Loop>>      outer_loop:none
    303   /// CHECK-DAG: <<Cnv:s\d+>>  TypeConversion [<<Shr>>]            loop:<<Loop>>      outer_loop:none
    304   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
    305   //
    306   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.halving_add_unsigned_constant(short[], short[]) loop_optimization (after)
    307   /// CHECK-DAG: <<UMAX:i\d+>> IntConstant 65535                     loop:none
    308   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<UMAX>>]         loop:none
    309   /// CHECK-DAG: <<Get:d\d+>>  VecLoad                               loop:<<Loop:B\d+>> outer_loop:none
    310   /// CHECK-DAG: <<HAdd:d\d+>> VecHalvingAdd [<<Get>>,<<Repl>>] packed_type:Uint16 rounded:false loop:<<Loop>> outer_loop:none
    311   /// CHECK-DAG:               VecStore [{{l\d+}},{{i\d+}},<<HAdd>>] loop:<<Loop>>      outer_loop:none
    312   private static void halving_add_unsigned_constant(short[] b1, short[] bo) {
    313     int min_length = Math.min(bo.length, b1.length);
    314     for (int i = 0; i < min_length; i++) {
    315       bo[i] = (short) (((b1[i] & 0xffff) + 0xffff) >> 1);
    316     }
    317   }
    318 
    319   public static void main(String[] args) {
    320     // Some interesting values.
    321     short[] interesting = {
    322       (short) 0x0000,
    323       (short) 0x0001,
    324       (short) 0x0002,
    325       (short) 0x1234,
    326       (short) 0x8000,
    327       (short) 0x8001,
    328       (short) 0x7fff,
    329       (short) 0xffff
    330     };
    331     // Initialize cross-values to test all cases, and also
    332     // set up some extra values to exercise the cleanup loop.
    333     for (int i = 0; i < M; i++) {
    334       sB1[i] = (short) i;
    335       sB2[i] = interesting[i & 7];
    336     }
    337 
    338     // Test halving add idioms.
    339     halving_add_signed(sB1, sB2, sBo);
    340     for (int i = 0; i < M; i++) {
    341       short e = (short) ((sB1[i] + sB2[i]) >> 1);
    342       expectEquals(e, sBo[i]);
    343     }
    344     halving_add_signed_alt(sB1, sB2, sBo);
    345     for (int i = 0; i < M; i++) {
    346       short e = (short) ((sB1[i] + sB2[i]) >> 1);
    347       expectEquals(e, sBo[i]);
    348     }
    349     halving_add_unsigned(sB1, sB2, sBo);
    350     for (int i = 0; i < M; i++) {
    351       short e = (short) (((sB1[i] & 0xffff) + (sB2[i] & 0xffff)) >> 1);
    352       expectEquals(e, sBo[i]);
    353     }
    354     rounding_halving_add_signed(sB1, sB2, sBo);
    355     for (int i = 0; i < M; i++) {
    356       short e = (short) ((sB1[i] + sB2[i] + 1) >> 1);
    357       expectEquals(e, sBo[i]);
    358     }
    359     rounding_halving_add_signed_alt(sB1, sB2, sBo);
    360     for (int i = 0; i < M; i++) {
    361       short e = (short) ((sB1[i] + sB2[i] + 1) >> 1);
    362       expectEquals(e, sBo[i]);
    363     }
    364     rounding_halving_add_signed_alt2(sB1, sB2, sBo);
    365     for (int i = 0; i < M; i++) {
    366       short e = (short) ((sB1[i] + sB2[i] + 1) >> 1);
    367       expectEquals(e, sBo[i]);
    368     }
    369     rounding_halving_add_unsigned(sB1, sB2, sBo);
    370     for (int i = 0; i < M; i++) {
    371       short e = (short) (((sB1[i] & 0xffff) + (sB2[i] & 0xffff) + 1) >> 1);
    372       expectEquals(e, sBo[i]);
    373     }
    374     rounding_halving_add_unsigned_alt(sB1, sB2, sBo);
    375     for (int i = 0; i < M; i++) {
    376       short e = (short) (((sB1[i] & 0xffff) + (sB2[i] & 0xffff) + 1) >> 1);
    377       expectEquals(e, sBo[i]);
    378     }
    379     halving_add_signed_constant(sB1, sBo);
    380     for (int i = 0; i < M; i++) {
    381       short e = (short) ((sB1[i] + 0x7fff) >> 1);
    382       expectEquals(e, sBo[i]);
    383     }
    384     halving_add_unsigned_constant(sB1, sBo);
    385     for (int i = 0; i < M; i++) {
    386       short e = (short) (((sB1[i] & 0xffff) + 0xffff) >> 1);
    387       expectEquals(e, sBo[i]);
    388     }
    389 
    390     System.out.println("passed");
    391   }
    392 
    393   private static void expectEquals(int expected, int result) {
    394     if (expected != result) {
    395       throw new Error("Expected: " + expected + ", found: " + result);
    396     }
    397   }
    398 }
    399