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 simple integral reductions: same type for accumulator and data.
     19  */
     20 public class Main {
     21 
     22   static final int N = 500;
     23   static final int M = 100;
     24 
     25   //
     26   // Basic reductions in loops.
     27   //
     28 
     29   // TODO: vectorize these (second step of b/64091002 plan)
     30 
     31   private static byte reductionByte(byte[] x) {
     32     byte sum = 0;
     33     for (int i = 0; i < x.length; i++) {
     34       sum += x[i];
     35     }
     36     return sum;
     37   }
     38 
     39   private static short reductionShort(short[] x) {
     40     short sum = 0;
     41     for (int i = 0; i < x.length; i++) {
     42       sum += x[i];
     43     }
     44     return sum;
     45   }
     46 
     47   private static char reductionChar(char[] x) {
     48     char sum = 0;
     49     for (int i = 0; i < x.length; i++) {
     50       sum += x[i];
     51     }
     52     return sum;
     53   }
     54 
     55   /// CHECK-START: int Main.reductionInt(int[]) loop_optimization (before)
     56   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
     57   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
     58   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
     59   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
     60   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
     61   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
     62   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
     63   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
     64   //
     65   /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.reductionInt(int[]) loop_optimization (after)
     66   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
     67   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
     68   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
     69   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
     70   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
     71   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
     72   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
     73   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
     74   private static int reductionInt(int[] x) {
     75     int sum = 0;
     76     for (int i = 0; i < x.length; i++) {
     77       sum += x[i];
     78     }
     79     return sum;
     80   }
     81 
     82   /// CHECK-START: int Main.reductionIntChain() loop_optimization (before)
     83   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
     84   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
     85   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons1>>,{{i\d+}}]      loop:<<Loop1:B\d+>> outer_loop:none
     86   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1>>      outer_loop:none
     87   /// CHECK-DAG: <<Get1:i\d+>>   ArrayGet [{{l\d+}},<<Phi2>>]  loop:<<Loop1>>      outer_loop:none
     88   /// CHECK-DAG:                 Add [<<Phi1>>,<<Get1>>]       loop:<<Loop1>>      outer_loop:none
     89   /// CHECK-DAG:                 Add [<<Phi2>>,<<Cons1>>]      loop:<<Loop1>>      outer_loop:none
     90   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop2:B\d+>> outer_loop:none
     91   /// CHECK-DAG: <<Phi4:i\d+>>   Phi [<<Phi1>>,{{i\d+}}]       loop:<<Loop2>>      outer_loop:none
     92   /// CHECK-DAG: <<Get2:i\d+>>   ArrayGet [{{l\d+}},<<Phi3>>]  loop:<<Loop2>>      outer_loop:none
     93   /// CHECK-DAG:                 Add [<<Phi4>>,<<Get2>>]       loop:<<Loop2>>      outer_loop:none
     94   /// CHECK-DAG:                 Add [<<Phi3>>,<<Cons1>>]      loop:<<Loop2>>      outer_loop:none
     95   /// CHECK-DAG:                 Return [<<Phi4>>]             loop:none
     96   //
     97   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
     98   //
     99   /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.reductionIntChain() loop_optimization (after)
    100   /// CHECK-DAG: <<Set1:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
    101   /// CHECK-DAG: <<Phi1:d\d+>>   Phi [<<Set1>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
    102   /// CHECK-DAG: <<Load1:d\d+>>  VecLoad [{{l\d+}},<<I1:i\d+>>] loop:<<Loop1>>      outer_loop:none
    103   /// CHECK-DAG:                 VecAdd [<<Phi1>>,<<Load1>>]    loop:<<Loop1>>      outer_loop:none
    104   /// CHECK-DAG:                 Add [<<I1>>,{{i\d+}}]          loop:<<Loop1>>      outer_loop:none
    105   /// CHECK-DAG: <<Red1:d\d+>>   VecReduce [<<Phi1>>]           loop:none
    106   /// CHECK-DAG: <<Extr1:i\d+>>  VecExtractScalar [<<Red1>>]    loop:none
    107   /// CHECK-DAG: <<Set2:d\d+>>   VecSetScalars [{{i\d+}}]       loop:none
    108   /// CHECK-DAG: <<Phi2:d\d+>>   Phi [<<Set2>>,{{d\d+}}]        loop:<<Loop2:B\d+>> outer_loop:none
    109   /// CHECK-DAG: <<Load2:d\d+>>  VecLoad [{{l\d+}},<<I2:i\d+>>] loop:<<Loop2>>      outer_loop:none
    110   /// CHECK-DAG:                 VecAdd [<<Phi2>>,<<Load2>>]    loop:<<Loop2>>      outer_loop:none
    111   /// CHECK-DAG:                 Add [<<I2>>,{{i\d+}}]          loop:<<Loop2>>      outer_loop:none
    112   /// CHECK-DAG: <<Red2:d\d+>>   VecReduce [<<Phi2>>]           loop:none
    113   /// CHECK-DAG: <<Extr2:i\d+>>  VecExtractScalar [<<Red2>>]    loop:none
    114   //
    115   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
    116   //
    117   // NOTE: pattern is robust with respect to vector loop unrolling and peeling.
    118   private static int reductionIntChain() {
    119     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
    120     int r = 1;
    121     for (int i = 0; i < 16; i++) {
    122       r += x[i];
    123     }
    124     for (int i = 0; i < 16; i++) {
    125       r += x[i];
    126     }
    127     return r;
    128   }
    129 
    130   /// CHECK-START: int Main.reductionIntToLoop(int[]) loop_optimization (before)
    131   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    132   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    133   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1:B\d+>> outer_loop:none
    134   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop1>>      outer_loop:none
    135   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop1>>      outer_loop:none
    136   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop1>>      outer_loop:none
    137   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop1>>      outer_loop:none
    138   /// CHECK-DAG: <<Phi3:i\d+>>   Phi [<<Phi2>>,{{i\d+}}]       loop:<<Loop2:B\d+>> outer_loop:none
    139   /// CHECK-DAG: <<Phi4:i\d+>>   Phi [<<Phi2>>,{{i\d+}}]       loop:<<Loop2>>      outer_loop:none
    140   //
    141   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
    142   //
    143   /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.reductionIntToLoop(int[]) loop_optimization (after)
    144   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
    145   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
    146   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop1:B\d+>> outer_loop:none
    147   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop1>>      outer_loop:none
    148   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop1>>      outer_loop:none
    149   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop1>>      outer_loop:none
    150   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    151   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
    152   private static int reductionIntToLoop(int[] x) {
    153     int r = 0;
    154     for (int i = 0; i < 8; i++) {
    155       r += x[i];
    156     }
    157     for (int i = r; i < 16; i++) {
    158       r += i;
    159     }
    160     return r;
    161   }
    162 
    163   /// CHECK-START: long Main.reductionLong(long[]) loop_optimization (before)
    164   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    165   /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
    166   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    167   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
    168   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
    169   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
    170   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
    171   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
    172   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
    173   //
    174   /// CHECK-START-{ARM64,MIPS64}: long Main.reductionLong(long[]) loop_optimization (after)
    175   /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
    176   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
    177   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
    178   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
    179   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
    180   /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
    181   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    182   /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
    183   private static long reductionLong(long[] x) {
    184     long sum = 0;
    185     for (int i = 0; i < x.length; i++) {
    186       sum += x[i];
    187     }
    188     return sum;
    189   }
    190 
    191   private static byte reductionByteM1(byte[] x) {
    192     byte sum = -1;
    193     for (int i = 0; i < x.length; i++) {
    194       sum += x[i];
    195     }
    196     return sum;
    197   }
    198 
    199   private static short reductionShortM1(short[] x) {
    200     short sum = -1;
    201     for (int i = 0; i < x.length; i++) {
    202       sum += x[i];
    203     }
    204     return sum;
    205   }
    206 
    207   private static char reductionCharM1(char[] x) {
    208     char sum = 0xffff;
    209     for (int i = 0; i < x.length; i++) {
    210       sum += x[i];
    211     }
    212     return sum;
    213   }
    214 
    215   /// CHECK-START: int Main.reductionIntM1(int[]) loop_optimization (before)
    216   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    217   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    218   /// CHECK-DAG: <<ConsM1:i\d+>> IntConstant -1                loop:none
    219   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
    220   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM1>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
    221   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
    222   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
    223   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
    224   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
    225   //
    226   /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.reductionIntM1(int[]) loop_optimization (after)
    227   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
    228   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
    229   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
    230   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
    231   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
    232   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
    233   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    234   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
    235   private static int reductionIntM1(int[] x) {
    236     int sum = -1;
    237     for (int i = 0; i < x.length; i++) {
    238       sum += x[i];
    239     }
    240     return sum;
    241   }
    242 
    243   /// CHECK-START: long Main.reductionLongM1(long[]) loop_optimization (before)
    244   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    245   /// CHECK-DAG: <<LongM1:j\d+>> LongConstant -1               loop:none
    246   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    247   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
    248   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<LongM1>>,{{j\d+}}]     loop:<<Loop>>      outer_loop:none
    249   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
    250   /// CHECK-DAG:                 Add [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
    251   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
    252   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
    253   //
    254   /// CHECK-START-{ARM64,MIPS64}: long Main.reductionLongM1(long[]) loop_optimization (after)
    255   /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
    256   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
    257   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
    258   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
    259   /// CHECK-DAG:                 VecAdd [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
    260   /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
    261   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    262   /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
    263   private static long reductionLongM1(long[] x) {
    264     long sum = -1L;
    265     for (int i = 0; i < x.length; i++) {
    266       sum += x[i];
    267     }
    268     return sum;
    269   }
    270 
    271   private static byte reductionMinusByte(byte[] x) {
    272     byte sum = 0;
    273     for (int i = 0; i < x.length; i++) {
    274       sum -= x[i];
    275     }
    276     return sum;
    277   }
    278 
    279   private static short reductionMinusShort(short[] x) {
    280     short sum = 0;
    281     for (int i = 0; i < x.length; i++) {
    282       sum -= x[i];
    283     }
    284     return sum;
    285   }
    286 
    287   private static char reductionMinusChar(char[] x) {
    288     char sum = 0;
    289     for (int i = 0; i < x.length; i++) {
    290       sum -= x[i];
    291     }
    292     return sum;
    293   }
    294 
    295   /// CHECK-START: int Main.reductionMinusInt(int[]) loop_optimization (before)
    296   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    297   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    298   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
    299   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
    300   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
    301   /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
    302   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
    303   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
    304   //
    305   /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.reductionMinusInt(int[]) loop_optimization (after)
    306   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
    307   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{i\d+}}]      loop:none
    308   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
    309   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
    310   /// CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
    311   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
    312   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    313   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
    314   private static int reductionMinusInt(int[] x) {
    315     int sum = 0;
    316     for (int i = 0; i < x.length; i++) {
    317       sum -= x[i];
    318     }
    319     return sum;
    320   }
    321 
    322   /// CHECK-START: long Main.reductionMinusLong(long[]) loop_optimization (before)
    323   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    324   /// CHECK-DAG: <<Long0:j\d+>>  LongConstant 0                loop:none
    325   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    326   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
    327   /// CHECK-DAG: <<Phi2:j\d+>>   Phi [<<Long0>>,{{j\d+}}]      loop:<<Loop>>      outer_loop:none
    328   /// CHECK-DAG: <<Get:j\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
    329   /// CHECK-DAG:                 Sub [<<Phi2>>,<<Get>>]        loop:<<Loop>>      outer_loop:none
    330   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
    331   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
    332   //
    333   /// CHECK-START-{ARM64,MIPS64}: long Main.reductionMinusLong(long[]) loop_optimization (after)
    334   /// CHECK-DAG: <<Cons2:i\d+>>  IntConstant 2                 loop:none
    335   /// CHECK-DAG: <<Set:d\d+>>    VecSetScalars [{{j\d+}}]      loop:none
    336   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
    337   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
    338   /// CHECK-DAG:                 VecSub [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
    339   /// CHECK-DAG:                 Add [<<I>>,<<Cons2>>]         loop:<<Loop>>      outer_loop:none
    340   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    341   /// CHECK-DAG: <<Extr:j\d+>>   VecExtractScalar [<<Red>>]    loop:none
    342   private static long reductionMinusLong(long[] x) {
    343     long sum = 0;
    344     for (int i = 0; i < x.length; i++) {
    345       sum -= x[i];
    346     }
    347     return sum;
    348   }
    349 
    350   private static byte reductionMinByte(byte[] x) {
    351     byte min = Byte.MAX_VALUE;
    352     for (int i = 0; i < x.length; i++) {
    353       min = (byte) Math.min(min, x[i]);
    354     }
    355     return min;
    356   }
    357 
    358   private static short reductionMinShort(short[] x) {
    359     short min = Short.MAX_VALUE;
    360     for (int i = 0; i < x.length; i++) {
    361       min = (short) Math.min(min, x[i]);
    362     }
    363     return min;
    364   }
    365 
    366   private static char reductionMinChar(char[] x) {
    367     char min = Character.MAX_VALUE;
    368     for (int i = 0; i < x.length; i++) {
    369       min = (char) Math.min(min, x[i]);
    370     }
    371     return min;
    372   }
    373 
    374   /// CHECK-START: int Main.reductionMinInt(int[]) loop_optimization (before)
    375   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    376   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    377   /// CHECK-DAG: <<ConsM:i\d+>>  IntConstant 2147483647        loop:none
    378   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
    379   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
    380   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
    381   /// CHECK-DAG:                 InvokeStaticOrDirect [<<Phi2>>,<<Get>>] intrinsic:MathMinIntInt loop:<<Loop>> outer_loop:none
    382   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
    383   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
    384   //
    385   /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.reductionMinInt(int[]) loop_optimization (after)
    386   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
    387   /// CHECK-DAG: <<Set:d\d+>>    VecReplicateScalar [{{i\d+}}] loop:none
    388   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
    389   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
    390   /// CHECK-DAG:                 VecMin [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
    391   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
    392   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    393   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
    394   private static int reductionMinInt(int[] x) {
    395     int min = Integer.MAX_VALUE;
    396     for (int i = 0; i < x.length; i++) {
    397       min = Math.min(min, x[i]);
    398     }
    399     return min;
    400   }
    401 
    402   private static long reductionMinLong(long[] x) {
    403     long min = Long.MAX_VALUE;
    404     for (int i = 0; i < x.length; i++) {
    405       min = Math.min(min, x[i]);
    406     }
    407     return min;
    408   }
    409 
    410   private static byte reductionMaxByte(byte[] x) {
    411     byte max = Byte.MIN_VALUE;
    412     for (int i = 0; i < x.length; i++) {
    413       max = (byte) Math.max(max, x[i]);
    414     }
    415     return max;
    416   }
    417 
    418   private static short reductionMaxShort(short[] x) {
    419     short max = Short.MIN_VALUE;
    420     for (int i = 0; i < x.length; i++) {
    421       max = (short) Math.max(max, x[i]);
    422     }
    423     return max;
    424   }
    425 
    426   private static char reductionMaxChar(char[] x) {
    427     char max = Character.MIN_VALUE;
    428     for (int i = 0; i < x.length; i++) {
    429       max = (char) Math.max(max, x[i]);
    430     }
    431     return max;
    432   }
    433 
    434   /// CHECK-START: int Main.reductionMaxInt(int[]) loop_optimization (before)
    435   /// CHECK-DAG: <<Cons0:i\d+>>  IntConstant 0                 loop:none
    436   /// CHECK-DAG: <<Cons1:i\d+>>  IntConstant 1                 loop:none
    437   /// CHECK-DAG: <<ConsM:i\d+>>  IntConstant -2147483648       loop:none
    438   /// CHECK-DAG: <<Phi1:i\d+>>   Phi [<<Cons0>>,{{i\d+}}]      loop:<<Loop:B\d+>> outer_loop:none
    439   /// CHECK-DAG: <<Phi2:i\d+>>   Phi [<<ConsM>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
    440   /// CHECK-DAG: <<Get:i\d+>>    ArrayGet [{{l\d+}},<<Phi1>>]  loop:<<Loop>>      outer_loop:none
    441   /// CHECK-DAG:                 InvokeStaticOrDirect [<<Phi2>>,<<Get>>] intrinsic:MathMaxIntInt loop:<<Loop>> outer_loop:none
    442   /// CHECK-DAG:                 Add [<<Phi1>>,<<Cons1>>]      loop:<<Loop>>      outer_loop:none
    443   /// CHECK-DAG:                 Return [<<Phi2>>]             loop:none
    444   //
    445   /// CHECK-START-{ARM,ARM64,MIPS64}: int Main.reductionMaxInt(int[]) loop_optimization (after)
    446   /// CHECK-DAG: <<Cons:i\d+>>   IntConstant {{2|4}}           loop:none
    447   /// CHECK-DAG: <<Set:d\d+>>    VecReplicateScalar [{{i\d+}}] loop:none
    448   /// CHECK-DAG: <<Phi:d\d+>>    Phi [<<Set>>,{{d\d+}}]        loop:<<Loop:B\d+>> outer_loop:none
    449   /// CHECK-DAG: <<Load:d\d+>>   VecLoad [{{l\d+}},<<I:i\d+>>] loop:<<Loop>>      outer_loop:none
    450   /// CHECK-DAG:                 VecMax [<<Phi>>,<<Load>>]     loop:<<Loop>>      outer_loop:none
    451   /// CHECK-DAG:                 Add [<<I>>,<<Cons>>]          loop:<<Loop>>      outer_loop:none
    452   /// CHECK-DAG: <<Red:d\d+>>    VecReduce [<<Phi>>]           loop:none
    453   /// CHECK-DAG: <<Extr:i\d+>>   VecExtractScalar [<<Red>>]    loop:none
    454   private static int reductionMaxInt(int[] x) {
    455     int max = Integer.MIN_VALUE;
    456     for (int i = 0; i < x.length; i++) {
    457       max = Math.max(max, x[i]);
    458     }
    459     return max;
    460   }
    461 
    462   private static long reductionMaxLong(long[] x) {
    463     long max = Long.MIN_VALUE;
    464     for (int i = 0; i < x.length; i++) {
    465       max = Math.max(max, x[i]);
    466     }
    467     return max;
    468   }
    469 
    470   //
    471   // A few special cases.
    472   //
    473 
    474   // TODO: consider unrolling
    475 
    476   private static int reductionInt10(int[] x) {
    477     int sum = 0;
    478     // Amenable to complete unrolling.
    479     for (int i = 10; i <= 10; i++) {
    480       sum += x[i];
    481     }
    482     return sum;
    483   }
    484 
    485   private static int reductionMinusInt10(int[] x) {
    486     int sum = 0;
    487     // Amenable to complete unrolling.
    488     for (int i = 10; i <= 10; i++) {
    489       sum -= x[i];
    490     }
    491     return sum;
    492   }
    493 
    494   private static int reductionMinInt10(int[] x) {
    495     int min = Integer.MAX_VALUE;
    496     // Amenable to complete unrolling.
    497     for (int i = 10; i <= 10; i++) {
    498       min = Math.min(min, x[i]);
    499     }
    500     return min;
    501   }
    502 
    503   private static int reductionMaxInt10(int[] x) {
    504     int max = Integer.MIN_VALUE;
    505     // Amenable to complete unrolling.
    506     for (int i = 10; i <= 10; i++) {
    507       max = Math.max(max, x[i]);
    508     }
    509     return max;
    510   }
    511 
    512   //
    513   // Main driver.
    514   //
    515 
    516   public static void main(String[] args) {
    517     byte[] xb = new byte[N];
    518     short[] xs = new short[N];
    519     char[] xc = new char[N];
    520     int[] xi = new int[N];
    521     long[] xl = new long[N];
    522     for (int i = 0, k = -17; i < N; i++, k += 3) {
    523       xb[i] = (byte) k;
    524       xs[i] = (short) k;
    525       xc[i] = (char) k;
    526       xi[i] = k;
    527       xl[i] = k;
    528     }
    529 
    530     // Arrays with all positive elements.
    531     byte[] xpb = new byte[M];
    532     short[] xps = new short[M];
    533     char[] xpc = new char[M];
    534     int[] xpi = new int[M];
    535     long[] xpl = new long[M];
    536     for (int i = 0, k = 3; i < M; i++, k++) {
    537       xpb[i] = (byte) k;
    538       xps[i] = (short) k;
    539       xpc[i] = (char) k;
    540       xpi[i] = k;
    541       xpl[i] = k;
    542     }
    543 
    544     // Arrays with all negative elements.
    545     byte[] xnb = new byte[M];
    546     short[] xns = new short[M];
    547     int[] xni = new int[M];
    548     long[] xnl = new long[M];
    549     for (int i = 0, k = -103; i < M; i++, k++) {
    550       xnb[i] = (byte) k;
    551       xns[i] = (short) k;
    552       xni[i] = k;
    553       xnl[i] = k;
    554     }
    555 
    556     // Test various reductions in loops.
    557     int[] x0 = { 0, 0, 0, 0, 0, 0, 0, 0 };
    558     int[] x1 = { 0, 0, 0, 1, 0, 0, 0, 0 };
    559     int[] x2 = { 1, 1, 1, 1, 0, 0, 0, 0 };
    560     expectEquals(-74, reductionByte(xb));
    561     expectEquals(-27466, reductionShort(xs));
    562     expectEquals(38070, reductionChar(xc));
    563     expectEquals(365750, reductionInt(xi));
    564     expectEquals(273, reductionIntChain());
    565     expectEquals(120, reductionIntToLoop(x0));
    566     expectEquals(121, reductionIntToLoop(x1));
    567     expectEquals(118, reductionIntToLoop(x2));
    568     expectEquals(-1310, reductionIntToLoop(xi));
    569     expectEquals(365750L, reductionLong(xl));
    570     expectEquals(-75, reductionByteM1(xb));
    571     expectEquals(-27467, reductionShortM1(xs));
    572     expectEquals(38069, reductionCharM1(xc));
    573     expectEquals(365749, reductionIntM1(xi));
    574     expectEquals(365749L, reductionLongM1(xl));
    575     expectEquals(74, reductionMinusByte(xb));
    576     expectEquals(27466, reductionMinusShort(xs));
    577     expectEquals(27466, reductionMinusChar(xc));
    578     expectEquals(-365750, reductionMinusInt(xi));
    579     expectEquals(365750L, reductionLong(xl));
    580     expectEquals(-75, reductionByteM1(xb));
    581     expectEquals(-27467, reductionShortM1(xs));
    582     expectEquals(38069, reductionCharM1(xc));
    583     expectEquals(365749, reductionIntM1(xi));
    584     expectEquals(365749L, reductionLongM1(xl));
    585     expectEquals(74, reductionMinusByte(xb));
    586     expectEquals(27466, reductionMinusShort(xs));
    587     expectEquals(27466, reductionMinusChar(xc));
    588     expectEquals(-365750, reductionMinusInt(xi));
    589     expectEquals(-365750L, reductionMinusLong(xl));
    590     expectEquals(-128, reductionMinByte(xb));
    591     expectEquals(-17, reductionMinShort(xs));
    592     expectEquals(1, reductionMinChar(xc));
    593     expectEquals(-17, reductionMinInt(xi));
    594     expectEquals(-17L, reductionMinLong(xl));
    595     expectEquals(3, reductionMinByte(xpb));
    596     expectEquals(3, reductionMinShort(xps));
    597     expectEquals(3, reductionMinChar(xpc));
    598     expectEquals(3, reductionMinInt(xpi));
    599     expectEquals(3L, reductionMinLong(xpl));
    600     expectEquals(-103, reductionMinByte(xnb));
    601     expectEquals(-103, reductionMinShort(xns));
    602     expectEquals(-103, reductionMinInt(xni));
    603     expectEquals(-103L, reductionMinLong(xnl));
    604     expectEquals(127, reductionMaxByte(xb));
    605     expectEquals(1480, reductionMaxShort(xs));
    606     expectEquals(65534, reductionMaxChar(xc));
    607     expectEquals(1480, reductionMaxInt(xi));
    608     expectEquals(1480L, reductionMaxLong(xl));
    609     expectEquals(102, reductionMaxByte(xpb));
    610     expectEquals(102, reductionMaxShort(xps));
    611     expectEquals(102, reductionMaxChar(xpc));
    612     expectEquals(102, reductionMaxInt(xpi));
    613     expectEquals(102L, reductionMaxLong(xpl));
    614     expectEquals(-4, reductionMaxByte(xnb));
    615     expectEquals(-4, reductionMaxShort(xns));
    616     expectEquals(-4, reductionMaxInt(xni));
    617     expectEquals(-4L, reductionMaxLong(xnl));
    618 
    619     // Test special cases.
    620     expectEquals(13, reductionInt10(xi));
    621     expectEquals(-13, reductionMinusInt10(xi));
    622     expectEquals(13, reductionMinInt10(xi));
    623     expectEquals(13, reductionMaxInt10(xi));
    624 
    625     System.out.println("passed");
    626   }
    627 
    628   private static void expectEquals(int expected, int result) {
    629     if (expected != result) {
    630       throw new Error("Expected: " + expected + ", found: " + result);
    631     }
    632   }
    633 
    634   private static void expectEquals(long expected, long result) {
    635     if (expected != result) {
    636       throw new Error("Expected: " + expected + ", found: " + result);
    637     }
    638   }
    639 }
    640