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 ABS vectorization.
     19  */
     20 public class Main {
     21 
     22   private static final int SPQUIET = 1 << 22;
     23   private static final long DPQUIET = 1L << 51;
     24 
     25   /// CHECK-START: void Main.doitByte(byte[]) loop_optimization (before)
     26   /// CHECK-DAG: Phi                                       loop:<<Loop:B\d+>> outer_loop:none
     27   /// CHECK-DAG: ArrayGet                                  loop:<<Loop>>      outer_loop:none
     28   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop>>      outer_loop:none
     29   /// CHECK-DAG: ArraySet                                  loop:<<Loop>>      outer_loop:none
     30   //
     31   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.doitByte(byte[]) loop_optimization (after)
     32   /// CHECK-DAG: VecLoad                                   loop:<<Loop1:B\d+>> outer_loop:none
     33   /// CHECK-DAG: VecAbs                                    loop:<<Loop1>>      outer_loop:none
     34   /// CHECK-DAG: VecStore                                  loop:<<Loop1>>      outer_loop:none
     35   /// CHECK-DAG: ArrayGet                                  loop:<<Loop2:B\d+>> outer_loop:none
     36   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop2>>      outer_loop:none
     37   /// CHECK-DAG: ArraySet                                  loop:<<Loop2>>      outer_loop:none
     38   //
     39   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
     40   //
     41   private static void doitByte(byte[] x) {
     42     for (int i = 0; i < x.length; i++) {
     43       x[i] = (byte) Math.abs(x[i]);
     44     }
     45   }
     46 
     47   /// CHECK-START: void Main.doitChar(char[]) loop_optimization (before)
     48   /// CHECK-DAG: Phi                                       loop:<<Loop:B\d+>> outer_loop:none
     49   /// CHECK-DAG: ArrayGet                                  loop:<<Loop>>      outer_loop:none
     50   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop>>      outer_loop:none
     51   /// CHECK-DAG: ArraySet                                  loop:<<Loop>>      outer_loop:none
     52   //
     53   /// CHECK-START: void Main.doitChar(char[]) loop_optimization (after)
     54   /// CHECK-NOT: VecAbs
     55   private static void doitChar(char[] x) {
     56     // Basically a nop due to zero extension.
     57     for (int i = 0; i < x.length; i++) {
     58       x[i] = (char) Math.abs(x[i]);
     59     }
     60   }
     61 
     62   /// CHECK-START: void Main.doitShort(short[]) loop_optimization (before)
     63   /// CHECK-DAG: Phi                                       loop:<<Loop:B\d+>> outer_loop:none
     64   /// CHECK-DAG: ArrayGet                                  loop:<<Loop>>      outer_loop:none
     65   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop>>      outer_loop:none
     66   /// CHECK-DAG: ArraySet                                  loop:<<Loop>>      outer_loop:none
     67   //
     68   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.doitShort(short[]) loop_optimization (after)
     69   /// CHECK-DAG: VecLoad                                   loop:<<Loop1:B\d+>> outer_loop:none
     70   /// CHECK-DAG: VecAbs                                    loop:<<Loop1>>      outer_loop:none
     71   /// CHECK-DAG: VecStore                                  loop:<<Loop1>>      outer_loop:none
     72   /// CHECK-DAG: ArrayGet                                  loop:<<Loop2:B\d+>> outer_loop:none
     73   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop2>>      outer_loop:none
     74   /// CHECK-DAG: ArraySet                                  loop:<<Loop2>>      outer_loop:none
     75   //
     76   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
     77   //
     78   private static void doitShort(short[] x) {
     79     for (int i = 0; i < x.length; i++) {
     80       x[i] = (short) Math.abs(x[i]);
     81     }
     82   }
     83 
     84   /// CHECK-START: void Main.doitCastedChar(char[]) loop_optimization (before)
     85   /// CHECK-DAG: Phi                                       loop:<<Loop:B\d+>> outer_loop:none
     86   /// CHECK-DAG: ArrayGet                                  loop:<<Loop>>      outer_loop:none
     87   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop>>      outer_loop:none
     88   /// CHECK-DAG: ArraySet                                  loop:<<Loop>>      outer_loop:none
     89   //
     90   /// CHECK-START-ARM64: void Main.doitCastedChar(char[]) loop_optimization (after)
     91   /// CHECK-DAG: VecLoad                                   loop:<<Loop1:B\d+>> outer_loop:none
     92   /// CHECK-DAG: VecAbs                                    loop:<<Loop1>>      outer_loop:none
     93   /// CHECK-DAG: VecStore                                  loop:<<Loop1>>      outer_loop:none
     94   /// CHECK-DAG: ArrayGet                                  loop:<<Loop2:B\d+>> outer_loop:none
     95   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop2>>      outer_loop:none
     96   /// CHECK-DAG: ArraySet                                  loop:<<Loop2>>      outer_loop:none
     97   //
     98   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
     99   //
    100   private static void doitCastedChar(char[] x) {
    101     for (int i = 0; i < x.length; i++) {
    102       x[i] = (char) Math.abs((short) x[i]);
    103     }
    104   }
    105 
    106   /// CHECK-START: void Main.doitInt(int[]) loop_optimization (before)
    107   /// CHECK-DAG: Phi                                       loop:<<Loop:B\d+>> outer_loop:none
    108   /// CHECK-DAG: ArrayGet                                  loop:<<Loop>>      outer_loop:none
    109   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop>>      outer_loop:none
    110   /// CHECK-DAG: ArraySet                                  loop:<<Loop>>      outer_loop:none
    111   //
    112   /// CHECK-START-{ARM,ARM64,MIPS64}: void Main.doitInt(int[]) loop_optimization (after)
    113   /// CHECK-DAG: VecLoad                                   loop:<<Loop1:B\d+>> outer_loop:none
    114   /// CHECK-DAG: VecAbs                                    loop:<<Loop1>>      outer_loop:none
    115   /// CHECK-DAG: VecStore                                  loop:<<Loop1>>      outer_loop:none
    116   /// CHECK-DAG: ArrayGet                                  loop:<<Loop2:B\d+>> outer_loop:none
    117   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop2>>      outer_loop:none
    118   /// CHECK-DAG: ArraySet                                  loop:<<Loop2>>      outer_loop:none
    119   //
    120   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
    121   //
    122   private static void doitInt(int[] x) {
    123     for (int i = 0; i < x.length; i++) {
    124       x[i] = Math.abs(x[i]);
    125     }
    126   }
    127 
    128   /// CHECK-START: void Main.doitLong(long[]) loop_optimization (before)
    129   /// CHECK-DAG: Phi                                        loop:<<Loop:B\d+>> outer_loop:none
    130   /// CHECK-DAG: ArrayGet                                   loop:<<Loop>>      outer_loop:none
    131   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsLong loop:<<Loop>>      outer_loop:none
    132   /// CHECK-DAG: ArraySet                                   loop:<<Loop>>      outer_loop:none
    133   //
    134   /// CHECK-START-{ARM64,MIPS64}: void Main.doitLong(long[]) loop_optimization (after)
    135   /// CHECK-DAG: VecLoad                                    loop:<<Loop1:B\d+>> outer_loop:none
    136   /// CHECK-DAG: VecAbs                                     loop:<<Loop1>>      outer_loop:none
    137   /// CHECK-DAG: VecStore                                   loop:<<Loop1>>      outer_loop:none
    138   /// CHECK-DAG: ArrayGet                                   loop:<<Loop2:B\d+>> outer_loop:none
    139   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsLong loop:<<Loop2>>      outer_loop:none
    140   /// CHECK-DAG: ArraySet                                   loop:<<Loop2>>      outer_loop:none
    141   //
    142   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
    143   //
    144   private static void doitLong(long[] x) {
    145     for (int i = 0; i < x.length; i++) {
    146       x[i] = Math.abs(x[i]);
    147     }
    148   }
    149 
    150   /// CHECK-START: void Main.doitFloat(float[]) loop_optimization (before)
    151   /// CHECK-DAG: Phi                                         loop:<<Loop:B\d+>> outer_loop:none
    152   /// CHECK-DAG: ArrayGet                                    loop:<<Loop>>      outer_loop:none
    153   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsFloat loop:<<Loop>>      outer_loop:none
    154   /// CHECK-DAG: ArraySet                                    loop:<<Loop>>      outer_loop:none
    155   //
    156   /// CHECK-START-{ARM64,MIPS64}: void Main.doitFloat(float[]) loop_optimization (after)
    157   /// CHECK-DAG: VecLoad                                     loop:<<Loop1:B\d+>> outer_loop:none
    158   /// CHECK-DAG: VecAbs                                      loop:<<Loop1>>      outer_loop:none
    159   /// CHECK-DAG: VecStore                                    loop:<<Loop1>>      outer_loop:none
    160   /// CHECK-DAG: ArrayGet                                    loop:<<Loop2:B\d+>> outer_loop:none
    161   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsFloat loop:<<Loop2>>      outer_loop:none
    162   /// CHECK-DAG: ArraySet                                    loop:<<Loop2>>      outer_loop:none
    163   //
    164   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
    165   //
    166   private static void doitFloat(float[] x) {
    167     for (int i = 0; i < x.length; i++) {
    168       x[i] = Math.abs(x[i]);
    169     }
    170   }
    171 
    172   /// CHECK-START: void Main.doitDouble(double[]) loop_optimization (before)
    173   /// CHECK-DAG: Phi                                          loop:<<Loop:B\d+>> outer_loop:none
    174   /// CHECK-DAG: ArrayGet                                     loop:<<Loop>>      outer_loop:none
    175   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsDouble loop:<<Loop>>      outer_loop:none
    176   /// CHECK-DAG: ArraySet                                     loop:<<Loop>>      outer_loop:none
    177   //
    178   /// CHECK-START-{ARM64,MIPS64}: void Main.doitDouble(double[]) loop_optimization (after)
    179   /// CHECK-DAG: VecLoad                                      loop:<<Loop1:B\d+>> outer_loop:none
    180   /// CHECK-DAG: VecAbs                                       loop:<<Loop1>>      outer_loop:none
    181   /// CHECK-DAG: VecStore                                     loop:<<Loop1>>      outer_loop:none
    182   /// CHECK-DAG: ArrayGet                                     loop:<<Loop2:B\d+>> outer_loop:none
    183   /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsDouble loop:<<Loop2>>      outer_loop:none
    184   /// CHECK-DAG: ArraySet                                     loop:<<Loop2>>      outer_loop:none
    185   //
    186   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
    187   //
    188   private static void doitDouble(double[] x) {
    189     for (int i = 0; i < x.length; i++) {
    190       x[i] = Math.abs(x[i]);
    191     }
    192   }
    193 
    194   public static void main(String[] args) {
    195     // Bytes, chars, shorts.
    196     byte[] xb = new byte[256];
    197     for (int i = 0; i < 256; i++) {
    198       xb[i] = (byte) i;
    199     }
    200     doitByte(xb);
    201     for (int i = 0; i < 256; i++) {
    202       expectEquals32((byte) Math.abs((byte) i), xb[i]);
    203     }
    204     char[] xc = new char[1024 * 64];
    205     for (int i = 0; i < 1024 * 64; i++) {
    206       xc[i] = (char) i;
    207     }
    208     doitChar(xc);
    209     for (int i = 0; i < 1024 * 64; i++) {
    210       expectEquals32((char) Math.abs((char) i), xc[i]);
    211     }
    212     short[] xs = new short[1024 * 64];
    213     for (int i = 0; i < 1024 * 64; i++) {
    214       xs[i] = (short) i;
    215     }
    216     doitShort(xs);
    217     for (int i = 0; i < 1024 * 64; i++) {
    218       expectEquals32((short) Math.abs((short) i), xs[i]);
    219     }
    220     for (int i = 0; i < 1024 * 64; i++) {
    221       xc[i] = (char) i;
    222     }
    223     doitCastedChar(xc);
    224     for (int i = 0; i < 1024 * 64; i++) {
    225       expectEquals32((char) Math.abs((short) i), xc[i]);
    226     }
    227     // Set up minint32, maxint32 and some others.
    228     int[] xi = new int[8];
    229     xi[0] = 0x80000000;
    230     xi[1] = 0x7fffffff;
    231     xi[2] = 0x80000001;
    232     xi[3] = -13;
    233     xi[4] = -1;
    234     xi[5] = 0;
    235     xi[6] = 1;
    236     xi[7] = 999;
    237     doitInt(xi);
    238     expectEquals32(0x80000000, xi[0]);
    239     expectEquals32(0x7fffffff, xi[1]);
    240     expectEquals32(0x7fffffff, xi[2]);
    241     expectEquals32(13, xi[3]);
    242     expectEquals32(1, xi[4]);
    243     expectEquals32(0, xi[5]);
    244     expectEquals32(1, xi[6]);
    245     expectEquals32(999, xi[7]);
    246 
    247     // Set up minint64, maxint64 and some others.
    248     long[] xl = new long[8];
    249     xl[0] = 0x8000000000000000L;
    250     xl[1] = 0x7fffffffffffffffL;
    251     xl[2] = 0x8000000000000001L;
    252     xl[3] = -13;
    253     xl[4] = -1;
    254     xl[5] = 0;
    255     xl[6] = 1;
    256     xl[7] = 999;
    257     doitLong(xl);
    258     expectEquals64(0x8000000000000000L, xl[0]);
    259     expectEquals64(0x7fffffffffffffffL, xl[1]);
    260     expectEquals64(0x7fffffffffffffffL, xl[2]);
    261     expectEquals64(13, xl[3]);
    262     expectEquals64(1, xl[4]);
    263     expectEquals64(0, xl[5]);
    264     expectEquals64(1, xl[6]);
    265     expectEquals64(999, xl[7]);
    266 
    267     // Set up float NaN and some others.
    268     float[] xf = new float[16];
    269     xf[0] = Float.intBitsToFloat(0x7f800001);
    270     xf[1] = Float.intBitsToFloat(0x7fa00000);
    271     xf[2] = Float.intBitsToFloat(0x7fc00000);
    272     xf[3] = Float.intBitsToFloat(0x7fffffff);
    273     xf[4] = Float.intBitsToFloat(0xff800001);
    274     xf[5] = Float.intBitsToFloat(0xffa00000);
    275     xf[6] = Float.intBitsToFloat(0xffc00000);
    276     xf[7] = Float.intBitsToFloat(0xffffffff);
    277     xf[8] = Float.NEGATIVE_INFINITY;
    278     xf[9] = -99.2f;
    279     xf[10] = -1.0f;
    280     xf[11] = -0.0f;
    281     xf[12] = +0.0f;
    282     xf[13] = +1.0f;
    283     xf[14] = +99.2f;
    284     xf[15] = Float.POSITIVE_INFINITY;
    285     doitFloat(xf);
    286     expectEqualsNaN32(0x7f800001, Float.floatToRawIntBits(xf[0]));
    287     expectEqualsNaN32(0x7fa00000, Float.floatToRawIntBits(xf[1]));
    288     expectEqualsNaN32(0x7fc00000, Float.floatToRawIntBits(xf[2]));
    289     expectEqualsNaN32(0x7fffffff, Float.floatToRawIntBits(xf[3]));
    290     expectEqualsNaN32(0x7f800001, Float.floatToRawIntBits(xf[4]));
    291     expectEqualsNaN32(0x7fa00000, Float.floatToRawIntBits(xf[5]));
    292     expectEqualsNaN32(0x7fc00000, Float.floatToRawIntBits(xf[6]));
    293     expectEqualsNaN32(0x7fffffff, Float.floatToRawIntBits(xf[7]));
    294     expectEquals32(
    295         Float.floatToRawIntBits(Float.POSITIVE_INFINITY),
    296         Float.floatToRawIntBits(xf[8]));
    297     expectEquals32(
    298         Float.floatToRawIntBits(99.2f),
    299         Float.floatToRawIntBits(xf[9]));
    300     expectEquals32(
    301         Float.floatToRawIntBits(1.0f),
    302         Float.floatToRawIntBits(xf[10]));
    303     expectEquals32(0, Float.floatToRawIntBits(xf[11]));
    304     expectEquals32(0, Float.floatToRawIntBits(xf[12]));
    305     expectEquals32(
    306         Float.floatToRawIntBits(1.0f),
    307         Float.floatToRawIntBits(xf[13]));
    308     expectEquals32(
    309         Float.floatToRawIntBits(99.2f),
    310         Float.floatToRawIntBits(xf[14]));
    311     expectEquals32(
    312         Float.floatToRawIntBits(Float.POSITIVE_INFINITY),
    313         Float.floatToRawIntBits(xf[15]));
    314 
    315     // Set up double NaN and some others.
    316     double[] xd = new double[16];
    317     xd[0] = Double.longBitsToDouble(0x7ff0000000000001L);
    318     xd[1] = Double.longBitsToDouble(0x7ff4000000000000L);
    319     xd[2] = Double.longBitsToDouble(0x7ff8000000000000L);
    320     xd[3] = Double.longBitsToDouble(0x7fffffffffffffffL);
    321     xd[4] = Double.longBitsToDouble(0xfff0000000000001L);
    322     xd[5] = Double.longBitsToDouble(0xfff4000000000000L);
    323     xd[6] = Double.longBitsToDouble(0xfff8000000000000L);
    324     xd[7] = Double.longBitsToDouble(0xffffffffffffffffL);
    325     xd[8] = Double.NEGATIVE_INFINITY;
    326     xd[9] = -99.2f;
    327     xd[10] = -1.0f;
    328     xd[11] = -0.0f;
    329     xd[12] = +0.0f;
    330     xd[13] = +1.0f;
    331     xd[14] = +99.2f;
    332     xd[15] = Double.POSITIVE_INFINITY;
    333     doitDouble(xd);
    334     expectEqualsNaN64(0x7ff0000000000001L, Double.doubleToRawLongBits(xd[0]));
    335     expectEqualsNaN64(0x7ff4000000000000L, Double.doubleToRawLongBits(xd[1]));
    336     expectEqualsNaN64(0x7ff8000000000000L, Double.doubleToRawLongBits(xd[2]));
    337     expectEqualsNaN64(0x7fffffffffffffffL, Double.doubleToRawLongBits(xd[3]));
    338     expectEqualsNaN64(0x7ff0000000000001L, Double.doubleToRawLongBits(xd[4]));
    339     expectEqualsNaN64(0x7ff4000000000000L, Double.doubleToRawLongBits(xd[5]));
    340     expectEqualsNaN64(0x7ff8000000000000L, Double.doubleToRawLongBits(xd[6]));
    341     expectEqualsNaN64(0x7fffffffffffffffL, Double.doubleToRawLongBits(xd[7]));
    342     expectEquals64(
    343         Double.doubleToRawLongBits(Double.POSITIVE_INFINITY),
    344         Double.doubleToRawLongBits(xd[8]));
    345     expectEquals64(
    346         Double.doubleToRawLongBits(99.2f),
    347         Double.doubleToRawLongBits(xd[9]));
    348     expectEquals64(
    349         Double.doubleToRawLongBits(1.0f),
    350         Double.doubleToRawLongBits(xd[10]));
    351     expectEquals64(0, Double.doubleToRawLongBits(xd[11]));
    352     expectEquals64(0, Double.doubleToRawLongBits(xd[12]));
    353     expectEquals64(
    354         Double.doubleToRawLongBits(1.0f),
    355         Double.doubleToRawLongBits(xd[13]));
    356     expectEquals64(
    357         Double.doubleToRawLongBits(99.2f),
    358         Double.doubleToRawLongBits(xd[14]));
    359     expectEquals64(
    360         Double.doubleToRawLongBits(Double.POSITIVE_INFINITY),
    361         Double.doubleToRawLongBits(xd[15]));
    362 
    363     System.out.println("passed");
    364   }
    365 
    366   private static void expectEquals32(int expected, int result) {
    367     if (expected != result) {
    368       throw new Error("Expected: " + expected + ", found: " + result);
    369     }
    370   }
    371 
    372   private static void expectEquals64(long expected, long result) {
    373     if (expected != result) {
    374       throw new Error("Expected: " + expected + ", found: " + result);
    375     }
    376   }
    377 
    378   // We allow that an expected NaN result has become quiet.
    379   private static void expectEqualsNaN32(int expected, int result) {
    380     if (expected != result && (expected | SPQUIET) != result) {
    381       throw new Error("Expected: 0x" + Integer.toHexString(expected)
    382           + ", found: 0x" + Integer.toHexString(result));
    383     }
    384   }
    385 
    386   // We allow that an expected NaN result has become quiet.
    387   private static void expectEqualsNaN64(long expected, long result) {
    388     if (expected != result && (expected | DPQUIET) != result) {
    389       throw new Error("Expected: 0x" + Long.toHexString(expected)
    390           + ", found: 0x" + Long.toHexString(result));
    391     }
    392   }
    393 }
    394