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  * Functional tests for SIMD vectorization.
     19  */
     20 public class Main {
     21 
     22   static byte[] a;
     23 
     24   //
     25   // Arithmetic operations.
     26   //
     27 
     28   /// CHECK-START: void Main.add(int) loop_optimization (before)
     29   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     30   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
     31   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
     32   //
     33   /// CHECK-START-ARM64: void Main.add(int) loop_optimization (after)
     34   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     35   /// CHECK-DAG: VecLoad  loop:<<Loop>>      outer_loop:none
     36   /// CHECK-DAG: VecAdd   loop:<<Loop>>      outer_loop:none
     37   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
     38   static void add(int x) {
     39     for (int i = 0; i < 128; i++)
     40       a[i] += x;
     41   }
     42 
     43   /// CHECK-START: void Main.sub(int) loop_optimization (before)
     44   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     45   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
     46   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
     47   //
     48   /// CHECK-START-ARM64: void Main.sub(int) loop_optimization (after)
     49   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     50   /// CHECK-DAG: VecLoad  loop:<<Loop>>      outer_loop:none
     51   /// CHECK-DAG: VecSub   loop:<<Loop>>      outer_loop:none
     52   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
     53   static void sub(int x) {
     54     for (int i = 0; i < 128; i++)
     55       a[i] -= x;
     56   }
     57 
     58   /// CHECK-START: void Main.mul(int) loop_optimization (before)
     59   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     60   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
     61   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
     62   //
     63   /// CHECK-START-ARM64: void Main.mul(int) loop_optimization (after)
     64   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     65   /// CHECK-DAG: VecLoad  loop:<<Loop>>      outer_loop:none
     66   /// CHECK-DAG: VecMul   loop:<<Loop>>      outer_loop:none
     67   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
     68   static void mul(int x) {
     69     for (int i = 0; i < 128; i++)
     70       a[i] *= x;
     71   }
     72 
     73   /// CHECK-START: void Main.div(int) loop_optimization (before)
     74   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     75   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
     76   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
     77   //
     78   /// CHECK-START: void Main.div(int) loop_optimization (after)
     79   //
     80   //  Not supported on any architecture.
     81   //
     82   static void div(int x) {
     83     for (int i = 0; i < 128; i++)
     84       a[i] /= x;
     85   }
     86 
     87   /// CHECK-START: void Main.neg() loop_optimization (before)
     88   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     89   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
     90   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
     91   //
     92   /// CHECK-START-ARM64: void Main.neg() loop_optimization (after)
     93   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
     94   /// CHECK-DAG: VecLoad  loop:<<Loop>>      outer_loop:none
     95   /// CHECK-DAG: VecNeg   loop:<<Loop>>      outer_loop:none
     96   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
     97   static void neg() {
     98     for (int i = 0; i < 128; i++)
     99       a[i] = (byte) -a[i];
    100   }
    101 
    102   /// CHECK-START: void Main.not() loop_optimization (before)
    103   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
    104   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
    105   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
    106   //
    107   /// CHECK-START-ARM64: void Main.not() loop_optimization (after)
    108   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
    109   /// CHECK-DAG: VecLoad  loop:<<Loop>>      outer_loop:none
    110   /// CHECK-DAG: VecNot   loop:<<Loop>>      outer_loop:none
    111   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
    112   static void not() {
    113     for (int i = 0; i < 128; i++)
    114       a[i] = (byte) ~a[i];
    115   }
    116 
    117   /// CHECK-START: void Main.shl4() loop_optimization (before)
    118   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
    119   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
    120   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
    121   //
    122   /// CHECK-START-ARM64: void Main.shl4() loop_optimization (after)
    123   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
    124   /// CHECK-DAG: VecLoad  loop:<<Loop>>      outer_loop:none
    125   /// CHECK-DAG: VecShl   loop:<<Loop>>      outer_loop:none
    126   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
    127   static void shl4() {
    128     for (int i = 0; i < 128; i++)
    129       a[i] <<= 4;
    130   }
    131 
    132   /// CHECK-START: void Main.sar2() loop_optimization (before)
    133   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
    134   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
    135   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
    136   //
    137   /// CHECK-START-ARM64: void Main.sar2() loop_optimization (after)
    138   //
    139   // TODO: fill in when supported
    140   static void sar2() {
    141     for (int i = 0; i < 128; i++)
    142       a[i] >>= 2;
    143   }
    144 
    145   /// CHECK-START: void Main.shr2() loop_optimization (before)
    146   /// CHECK-DAG: Phi      loop:<<Loop:B\d+>> outer_loop:none
    147   /// CHECK-DAG: ArrayGet loop:<<Loop>>      outer_loop:none
    148   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
    149   //
    150   /// CHECK-START-ARM64: void Main.shr2() loop_optimization (after)
    151   //
    152   // TODO: fill in when supported
    153   static void shr2() {
    154     for (int i = 0; i < 128; i++)
    155       a[i] >>>= 2;
    156   }
    157 
    158   //
    159   // Shift sanity.
    160   //
    161 
    162   static void sar31() {
    163     for (int i = 0; i < 128; i++)
    164       a[i] >>= 31;
    165   }
    166 
    167   static void shr31() {
    168     for (int i = 0; i < 128; i++)
    169       a[i] >>>= 31;
    170   }
    171 
    172   static void shr32() {
    173     for (int i = 0; i < 128; i++)
    174       a[i] >>>= 32;  // 0, since & 31
    175   }
    176 
    177   static void shr33() {
    178     for (int i = 0; i < 128; i++)
    179       a[i] >>>= 33;  // 1, since & 31
    180   }
    181 
    182   static void shl9() {
    183     for (int i = 0; i < 128; i++)
    184       a[i] <<= 9;  // yields all-zeros
    185   }
    186 
    187   //
    188   // Loop bounds.
    189   //
    190 
    191   static void bounds() {
    192     for (int i = 1; i < 127; i++)
    193       a[i] += 11;
    194   }
    195 
    196   //
    197   // Test Driver.
    198   //
    199 
    200   public static void main(String[] args) {
    201     // Set up.
    202     a = new byte[128];
    203     for (int i = 0; i < 128; i++) {
    204       a[i] = (byte) i;
    205     }
    206     // Arithmetic operations.
    207     add(2);
    208     for (int i = 0; i < 128; i++) {
    209       expectEquals((byte)(i + 2), a[i], "add");
    210     }
    211     sub(2);
    212     for (int i = 0; i < 128; i++) {
    213       expectEquals(i, a[i], "sub");
    214     }
    215     mul(2);
    216     for (int i = 0; i < 128; i++) {
    217       expectEquals((byte)(i + i), a[i], "mul");
    218     }
    219     div(2);
    220     for (int i = 0; i < 128; i++) {
    221       expectEquals(((byte)(i + i)) >> 1, a[i], "div");
    222       a[i] = (byte) i;  // undo arithmetic wrap-around effects
    223     }
    224     neg();
    225     for (int i = 0; i < 128; i++) {
    226       expectEquals(-i, a[i], "neg");
    227     }
    228     // Loop bounds.
    229     bounds();
    230     expectEquals(0, a[0], "bounds0");
    231     for (int i = 1; i < 127; i++) {
    232       expectEquals(11 - i, a[i], "bounds");
    233     }
    234     expectEquals(-127, a[127], "bounds127");
    235     // Shifts.
    236     for (int i = 0; i < 128; i++) {
    237       a[i] = (byte) 0xff;
    238     }
    239     shl4();
    240     for (int i = 0; i < 128; i++) {
    241       expectEquals((byte) 0xf0, a[i], "shl4");
    242     }
    243     sar2();
    244     for (int i = 0; i < 128; i++) {
    245       expectEquals((byte) 0xfc, a[i], "sar2");
    246     }
    247     shr2();
    248     for (int i = 0; i < 128; i++) {
    249       expectEquals((byte) 0xff, a[i], "shr2");  // sic!
    250     }
    251     sar31();
    252     for (int i = 0; i < 128; i++) {
    253       expectEquals((byte) 0xff, a[i], "sar31");
    254     }
    255     shr31();
    256     for (int i = 0; i < 128; i++) {
    257       expectEquals(0x01, a[i], "shr31");
    258       a[i] = (byte) 0x12;  // reset
    259     }
    260     shr32();
    261     for (int i = 0; i < 128; i++) {
    262       expectEquals((byte) 0x12, a[i], "shr32");
    263     }
    264     shr33();
    265     for (int i = 0; i < 128; i++) {
    266       expectEquals((byte) 0x09, a[i], "shr33");
    267     }
    268     shl9();
    269     for (int i = 0; i < 128; i++) {
    270       expectEquals((byte) 0x00, a[i], "shl9");
    271       a[i] = (byte) 0xf0;  // reset
    272     }
    273     not();
    274     for (int i = 0; i < 128; i++) {
    275       expectEquals((byte) 0x0f, a[i], "not");
    276     }
    277     // Done.
    278     System.out.println("passed");
    279   }
    280 
    281   private static void expectEquals(int expected, int result, String action) {
    282     if (expected != result) {
    283       throw new Error("Expected: " + expected + ", found: " + result + " for " + action);
    284     }
    285   }
    286 }
    287