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