Aart Bik | 6daebeb | 2017-04-03 14:35:41 -0700 | [diff] [blame] | 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 | |
Aart Bik | 9899026 | 2017-04-10 13:15:57 -0700 | [diff] [blame] | 25 | /// CHECK-START: void Main.doitInt(int[]) 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-ARM64: void Main.doitInt(int[]) loop_optimization (after) |
| 32 | /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none |
| 33 | /// CHECK-DAG: VecLoad loop:<<Loop1>> outer_loop:none |
| 34 | /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none |
| 35 | /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none |
| 36 | /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none |
| 37 | /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:none |
| 38 | /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsInt loop:<<Loop2>> outer_loop:none |
| 39 | /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none |
| 40 | // |
| 41 | /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" |
Aart Bik | 6daebeb | 2017-04-03 14:35:41 -0700 | [diff] [blame] | 42 | private static void doitInt(int[] x) { |
| 43 | for (int i = 0; i < x.length; i++) { |
| 44 | x[i] = Math.abs(x[i]); |
| 45 | } |
| 46 | } |
| 47 | |
Aart Bik | 9899026 | 2017-04-10 13:15:57 -0700 | [diff] [blame] | 48 | /// CHECK-START: void Main.doitLong(long[]) loop_optimization (before) |
| 49 | /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| 50 | /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none |
| 51 | /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsLong loop:<<Loop>> outer_loop:none |
| 52 | /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none |
| 53 | // |
| 54 | /// CHECK-START-ARM64: void Main.doitLong(long[]) loop_optimization (after) |
| 55 | // |
| 56 | // TODO: Not supported yet. |
Aart Bik | 6daebeb | 2017-04-03 14:35:41 -0700 | [diff] [blame] | 57 | private static void doitLong(long[] x) { |
| 58 | for (int i = 0; i < x.length; i++) { |
| 59 | x[i] = Math.abs(x[i]); |
| 60 | } |
| 61 | } |
| 62 | |
Aart Bik | 9899026 | 2017-04-10 13:15:57 -0700 | [diff] [blame] | 63 | /// CHECK-START: void Main.doitFloat(float[]) loop_optimization (before) |
| 64 | /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| 65 | /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none |
| 66 | /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsFloat loop:<<Loop>> outer_loop:none |
| 67 | /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none |
| 68 | // |
| 69 | /// CHECK-START-ARM64: void Main.doitFloat(float[]) loop_optimization (after) |
| 70 | /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none |
| 71 | /// CHECK-DAG: VecLoad loop:<<Loop1>> outer_loop:none |
| 72 | /// CHECK-DAG: VecAbs loop:<<Loop1>> outer_loop:none |
| 73 | /// CHECK-DAG: VecStore loop:<<Loop1>> outer_loop:none |
| 74 | /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none |
| 75 | /// CHECK-DAG: ArrayGet loop:<<Loop2>> outer_loop:none |
| 76 | /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsFloat loop:<<Loop2>> outer_loop:none |
| 77 | /// CHECK-DAG: ArraySet loop:<<Loop2>> outer_loop:none |
| 78 | // |
| 79 | /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>" |
Aart Bik | 6daebeb | 2017-04-03 14:35:41 -0700 | [diff] [blame] | 80 | private static void doitFloat(float[] x) { |
| 81 | for (int i = 0; i < x.length; i++) { |
| 82 | x[i] = Math.abs(x[i]); |
| 83 | } |
| 84 | } |
| 85 | |
Aart Bik | 9899026 | 2017-04-10 13:15:57 -0700 | [diff] [blame] | 86 | /// CHECK-START: void Main.doitDouble(double[]) loop_optimization (before) |
| 87 | /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none |
| 88 | /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none |
| 89 | /// CHECK-DAG: InvokeStaticOrDirect intrinsic:MathAbsDouble loop:<<Loop>> outer_loop:none |
| 90 | /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none |
| 91 | // |
| 92 | /// CHECK-START-ARM64: void Main.doitDouble(double[]) loop_optimization (after) |
| 93 | // |
| 94 | // TODO: Not supported yet. |
Aart Bik | 6daebeb | 2017-04-03 14:35:41 -0700 | [diff] [blame] | 95 | private static void doitDouble(double[] x) { |
| 96 | for (int i = 0; i < x.length; i++) { |
| 97 | x[i] = Math.abs(x[i]); |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | public static void main(String[] args) { |
| 102 | // Set up minint32, maxint32 and some others. |
| 103 | int[] xi = new int[8]; |
| 104 | xi[0] = 0x80000000; |
| 105 | xi[1] = 0x7fffffff; |
| 106 | xi[2] = 0x80000001; |
| 107 | xi[3] = -13; |
| 108 | xi[4] = -1; |
| 109 | xi[5] = 0; |
| 110 | xi[6] = 1; |
| 111 | xi[7] = 999; |
| 112 | doitInt(xi); |
| 113 | expectEquals32(0x80000000, xi[0]); |
| 114 | expectEquals32(0x7fffffff, xi[1]); |
| 115 | expectEquals32(0x7fffffff, xi[2]); |
| 116 | expectEquals32(13, xi[3]); |
| 117 | expectEquals32(1, xi[4]); |
| 118 | expectEquals32(0, xi[5]); |
| 119 | expectEquals32(1, xi[6]); |
| 120 | expectEquals32(999, xi[7]); |
| 121 | |
| 122 | // Set up minint64, maxint64 and some others. |
| 123 | long[] xl = new long[8]; |
| 124 | xl[0] = 0x8000000000000000L; |
| 125 | xl[1] = 0x7fffffffffffffffL; |
| 126 | xl[2] = 0x8000000000000001L; |
| 127 | xl[3] = -13; |
| 128 | xl[4] = -1; |
| 129 | xl[5] = 0; |
| 130 | xl[6] = 1; |
| 131 | xl[7] = 999; |
| 132 | doitLong(xl); |
| 133 | expectEquals64(0x8000000000000000L, xl[0]); |
| 134 | expectEquals64(0x7fffffffffffffffL, xl[1]); |
| 135 | expectEquals64(0x7fffffffffffffffL, xl[2]); |
| 136 | expectEquals64(13, xl[3]); |
| 137 | expectEquals64(1, xl[4]); |
| 138 | expectEquals64(0, xl[5]); |
| 139 | expectEquals64(1, xl[6]); |
| 140 | expectEquals64(999, xl[7]); |
| 141 | |
| 142 | // Set up float NaN and some others. |
| 143 | float[] xf = new float[16]; |
| 144 | xf[0] = Float.intBitsToFloat(0x7f800001); |
| 145 | xf[1] = Float.intBitsToFloat(0x7fa00000); |
| 146 | xf[2] = Float.intBitsToFloat(0x7fc00000); |
| 147 | xf[3] = Float.intBitsToFloat(0x7fffffff); |
| 148 | xf[4] = Float.intBitsToFloat(0xff800001); |
| 149 | xf[5] = Float.intBitsToFloat(0xffa00000); |
| 150 | xf[6] = Float.intBitsToFloat(0xffc00000); |
| 151 | xf[7] = Float.intBitsToFloat(0xffffffff); |
| 152 | xf[8] = Float.NEGATIVE_INFINITY; |
| 153 | xf[9] = -99.2f; |
| 154 | xf[10] = -1.0f; |
| 155 | xf[11] = -0.0f; |
| 156 | xf[12] = +0.0f; |
| 157 | xf[13] = +1.0f; |
| 158 | xf[14] = +99.2f; |
| 159 | xf[15] = Float.POSITIVE_INFINITY; |
| 160 | doitFloat(xf); |
| 161 | expectEqualsNaN32(0x7f800001, Float.floatToRawIntBits(xf[0])); |
| 162 | expectEqualsNaN32(0x7fa00000, Float.floatToRawIntBits(xf[1])); |
| 163 | expectEqualsNaN32(0x7fc00000, Float.floatToRawIntBits(xf[2])); |
| 164 | expectEqualsNaN32(0x7fffffff, Float.floatToRawIntBits(xf[3])); |
| 165 | expectEqualsNaN32(0x7f800001, Float.floatToRawIntBits(xf[4])); |
| 166 | expectEqualsNaN32(0x7fa00000, Float.floatToRawIntBits(xf[5])); |
| 167 | expectEqualsNaN32(0x7fc00000, Float.floatToRawIntBits(xf[6])); |
| 168 | expectEqualsNaN32(0x7fffffff, Float.floatToRawIntBits(xf[7])); |
| 169 | expectEquals32( |
| 170 | Float.floatToRawIntBits(Float.POSITIVE_INFINITY), |
| 171 | Float.floatToRawIntBits(xf[8])); |
| 172 | expectEquals32( |
| 173 | Float.floatToRawIntBits(99.2f), |
| 174 | Float.floatToRawIntBits(xf[9])); |
| 175 | expectEquals32( |
| 176 | Float.floatToRawIntBits(1.0f), |
| 177 | Float.floatToRawIntBits(xf[10])); |
| 178 | expectEquals32(0, Float.floatToRawIntBits(xf[11])); |
| 179 | expectEquals32(0, Float.floatToRawIntBits(xf[12])); |
| 180 | expectEquals32( |
| 181 | Float.floatToRawIntBits(1.0f), |
| 182 | Float.floatToRawIntBits(xf[13])); |
| 183 | expectEquals32( |
| 184 | Float.floatToRawIntBits(99.2f), |
| 185 | Float.floatToRawIntBits(xf[14])); |
| 186 | expectEquals32( |
| 187 | Float.floatToRawIntBits(Float.POSITIVE_INFINITY), |
| 188 | Float.floatToRawIntBits(xf[15])); |
| 189 | |
| 190 | // Set up double NaN and some others. |
| 191 | double[] xd = new double[16]; |
| 192 | xd[0] = Double.longBitsToDouble(0x7ff0000000000001L); |
| 193 | xd[1] = Double.longBitsToDouble(0x7ff4000000000000L); |
| 194 | xd[2] = Double.longBitsToDouble(0x7ff8000000000000L); |
| 195 | xd[3] = Double.longBitsToDouble(0x7fffffffffffffffL); |
| 196 | xd[4] = Double.longBitsToDouble(0xfff0000000000001L); |
| 197 | xd[5] = Double.longBitsToDouble(0xfff4000000000000L); |
| 198 | xd[6] = Double.longBitsToDouble(0xfff8000000000000L); |
| 199 | xd[7] = Double.longBitsToDouble(0xffffffffffffffffL); |
| 200 | xd[8] = Double.NEGATIVE_INFINITY; |
| 201 | xd[9] = -99.2f; |
| 202 | xd[10] = -1.0f; |
| 203 | xd[11] = -0.0f; |
| 204 | xd[12] = +0.0f; |
| 205 | xd[13] = +1.0f; |
| 206 | xd[14] = +99.2f; |
| 207 | xd[15] = Double.POSITIVE_INFINITY; |
| 208 | doitDouble(xd); |
| 209 | expectEqualsNaN64(0x7ff0000000000001L, Double.doubleToRawLongBits(xd[0])); |
| 210 | expectEqualsNaN64(0x7ff4000000000000L, Double.doubleToRawLongBits(xd[1])); |
| 211 | expectEqualsNaN64(0x7ff8000000000000L, Double.doubleToRawLongBits(xd[2])); |
| 212 | expectEqualsNaN64(0x7fffffffffffffffL, Double.doubleToRawLongBits(xd[3])); |
| 213 | expectEqualsNaN64(0x7ff0000000000001L, Double.doubleToRawLongBits(xd[4])); |
| 214 | expectEqualsNaN64(0x7ff4000000000000L, Double.doubleToRawLongBits(xd[5])); |
| 215 | expectEqualsNaN64(0x7ff8000000000000L, Double.doubleToRawLongBits(xd[6])); |
| 216 | expectEqualsNaN64(0x7fffffffffffffffL, Double.doubleToRawLongBits(xd[7])); |
| 217 | expectEquals64( |
| 218 | Double.doubleToRawLongBits(Double.POSITIVE_INFINITY), |
| 219 | Double.doubleToRawLongBits(xd[8])); |
| 220 | expectEquals64( |
| 221 | Double.doubleToRawLongBits(99.2f), |
| 222 | Double.doubleToRawLongBits(xd[9])); |
| 223 | expectEquals64( |
| 224 | Double.doubleToRawLongBits(1.0f), |
| 225 | Double.doubleToRawLongBits(xd[10])); |
| 226 | expectEquals64(0, Double.doubleToRawLongBits(xd[11])); |
| 227 | expectEquals64(0, Double.doubleToRawLongBits(xd[12])); |
| 228 | expectEquals64( |
| 229 | Double.doubleToRawLongBits(1.0f), |
| 230 | Double.doubleToRawLongBits(xd[13])); |
| 231 | expectEquals64( |
| 232 | Double.doubleToRawLongBits(99.2f), |
| 233 | Double.doubleToRawLongBits(xd[14])); |
| 234 | expectEquals64( |
| 235 | Double.doubleToRawLongBits(Double.POSITIVE_INFINITY), |
| 236 | Double.doubleToRawLongBits(xd[15])); |
| 237 | |
| 238 | System.out.println("passed"); |
| 239 | } |
| 240 | |
| 241 | private static void expectEquals32(int expected, int result) { |
| 242 | if (expected != result) { |
| 243 | throw new Error("Expected: " + expected + ", found: " + result); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | private static void expectEquals64(long expected, long result) { |
| 248 | if (expected != result) { |
| 249 | throw new Error("Expected: " + expected + ", found: " + result); |
| 250 | } |
| 251 | } |
| 252 | |
| 253 | // We allow that an expected NaN result has become quiet. |
| 254 | private static void expectEqualsNaN32(int expected, int result) { |
| 255 | if (expected != result && (expected | SPQUIET) != result) { |
| 256 | throw new Error("Expected: 0x" + Integer.toHexString(expected) |
| 257 | + ", found: 0x" + Integer.toHexString(result)); |
| 258 | } |
| 259 | } |
| 260 | |
| 261 | // We allow that an expected NaN result has become quiet. |
| 262 | private static void expectEqualsNaN64(long expected, long result) { |
| 263 | if (expected != result && (expected | DPQUIET) != result) { |
| 264 | throw new Error("Expected: 0x" + Long.toHexString(expected) |
| 265 | + ", found: 0x" + Long.toHexString(result)); |
| 266 | } |
| 267 | } |
| 268 | } |