1 /* 2 * Copyright (C) 2019 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 public class Main { 18 // Based on Linpack.matgen 19 // Load-store elimination did not work when a function had SIMD code. 20 // In the test below loop B is vectorized. 21 // Check that a redundant ArrayGet is eliminated in loop A. 22 23 /// CHECK-START: double Main.$noinline$vecgen(double[], double[], int) load_store_elimination (before) 24 /// CHECK: Rem 25 /// CHECK-NEXT: TypeConversion 26 /// CHECK-NEXT: Sub 27 /// CHECK-NEXT: Mul 28 /// CHECK-NEXT: ArraySet 29 /// CHECK-NEXT: ArrayGet 30 /// CHECK-NEXT: LessThanOrEqual 31 /// CHECK-NEXT: Select 32 /// CHECK-NEXT: Add 33 /// CHECK-NEXT: Goto loop:{{B\d+}} 34 35 /// CHECK-START: double Main.$noinline$vecgen(double[], double[], int) load_store_elimination (after) 36 /// CHECK: Rem 37 /// CHECK-NEXT: TypeConversion 38 /// CHECK-NEXT: Sub 39 /// CHECK-NEXT: Mul 40 /// CHECK-NEXT: ArraySet 41 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 42 // 43 /// CHECK-NEXT: ArrayGet 44 // 45 /// CHECK-FI: 46 /// CHECK-NEXT: LessThanOrEqual 47 /// CHECK-NEXT: Select 48 /// CHECK-NEXT: Add 49 /// CHECK-NEXT: Goto loop:{{B\d+}} 50 // 51 // TODO: reenable LSE for graphs with Predicated SIMD. $noinline$vecgen(double a[], double b[], int n)52 static double $noinline$vecgen(double a[], double b[], int n) { 53 double norma = 0.0; 54 int init = 1325; 55 // Loop A 56 for (int i = 0; i < n; ++i) { 57 init = 3125*init % 65536; 58 a[i] = (init - 32768.0)/16384.0; 59 norma = (a[i] > norma) ? a[i] : norma; // ArrayGet should be removed by LSE. 60 } 61 62 // Loop B 63 for (int i = 0; i < n; ++i) { 64 b[i] += a[i]; 65 } 66 67 return norma; 68 } 69 70 test01()71 static void test01() { 72 double a[] = new double[1024]; 73 double norma = $noinline$vecgen(a, a, a.length); 74 System.out.println((int)norma); 75 System.out.println((int)a[1023]); 76 } 77 78 // Check LSE works when a function has SIMD code. 79 // 80 /// CHECK-START: double Main.$noinline$test02(double[], int) load_store_elimination (before) 81 /// CHECK: BoundsCheck loop:none 82 /// CHECK-NEXT: ArrayGet 83 /// CHECK-NEXT: Mul 84 /// CHECK-NEXT: ArraySet 85 /// CHECK-NEXT: ArrayGet 86 /// CHECK-NEXT: ArrayLength 87 /// CHECK-NEXT: BelowOrEqual 88 // 89 /// CHECK: ArrayGet loop:none 90 /// CHECK-NEXT: Return 91 92 /// CHECK-START: double Main.$noinline$test02(double[], int) load_store_elimination (after) 93 /// CHECK: BoundsCheck loop:none 94 /// CHECK-NEXT: ArrayGet 95 /// CHECK-NEXT: Mul 96 /// CHECK-NEXT: ArraySet 97 /// CHECK-IF: hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true' 98 // 99 /// CHECK-NEXT: ArrayGet 100 // 101 /// CHECK-FI: 102 /// CHECK-NEXT: ArrayLength 103 /// CHECK-NEXT: BelowOrEqual 104 // 105 /// CHECK: Return 106 // 107 // TODO: reenable LSE for graphs with Predicated SIMD. $noinline$test02(double a[], int n)108 static double $noinline$test02(double a[], int n) { 109 double b[] = new double[n]; 110 a[0] = a[0] / 2; 111 112 double norma = a[0]; // ArrayGet should be removed by LSE. 113 114 // The following loop is vectorized. 115 for (int i = 0; i < 128; ++i) { 116 b[i] += a[i]; 117 } 118 119 norma = a[0]; // ArrayGet should be removed by LSE. 120 return norma; 121 } 122 test02()123 static void test02() { 124 double a[] = new double[128]; 125 java.util.Arrays.fill(a, 2.0); 126 double norma = $noinline$test02(a, a.length); 127 System.out.println((int)norma); 128 } 129 130 // Check LSE works when a function has SIMD code. 131 // 132 /// CHECK-START: double Main.$noinline$test03(int) load_store_elimination (before) 133 /// CHECK: ArrayGet loop:none 134 /// CHECK-NEXT: Return 135 136 /// CHECK-START: double Main.$noinline$test03(int) load_store_elimination (after) 137 /// CHECK-IF: not (hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true') 138 // 139 /// CHECK-NOT: ArrayGet loop:none 140 // 141 /// CHECK-FI: 142 // 143 // TODO: reenable LSE for graphs with Predicated SIMD. $noinline$test03(int n)144 static double $noinline$test03(int n) { 145 double a[] = new double[n]; 146 double b[] = new double[n]; 147 148 a[0] = 2.0; 149 150 // The following loop is vectorized. 151 for (int i = 0; i < 128; ++i) { 152 b[i] += a[i]; 153 } 154 155 a[0] = 2.0; 156 return a[0]; // ArrayGet should be removed by LSE. 157 } 158 test03()159 static void test03() { 160 double norma = $noinline$test03(128); 161 System.out.println((int)norma); 162 } 163 164 // Check LSE eliminates VecLoad. 165 // 166 /// CHECK-START-ARM64: double[] Main.$noinline$test04(int) load_store_elimination (before) 167 /// CHECK: VecStore 168 /// CHECK: VecLoad 169 /// CHECK: VecAdd 170 /// CHECK: VecStore 171 /// CHECK: Add 172 /// CHECK: Goto loop:{{B\d+}} 173 174 /// CHECK-START-ARM64: double[] Main.$noinline$test04(int) load_store_elimination (after) 175 /// CHECK-IF: not (hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true') 176 // 177 // In NEON case there is a post-loop which prevents the store to be removed. 178 /// CHECK: VecStore 179 // 180 /// CHECK-FI: 181 // 182 /// CHECK: VecAdd 183 /// CHECK: VecStore 184 /// CHECK: Add 185 /// CHECK: Goto loop:{{B\d+}} 186 // 187 188 /// CHECK-IF: not (hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true') 189 // 190 /// CHECK-NOT: VecStore 191 // 192 /// CHECK-FI: 193 // 194 // TODO: reenable LSE for graphs with Predicated SIMD. $noinline$test04(int n)195 static double[] $noinline$test04(int n) { 196 double a[] = new double[n]; 197 double b[] = new double[n]; 198 199 // The following loop is vectorized. 200 for (int i = 0; i < n; ++i) { 201 a[i] = 1; 202 b[i] = a[i] + a[i]; // VecLoad should be removed by LSE. 203 } 204 205 return b; 206 } 207 test04()208 static void test04() { 209 double norma = $noinline$test04(128)[0]; 210 System.out.println((int)norma); 211 } 212 213 // Check LSE eliminates VecLoad. 214 // 215 /// CHECK-START-ARM64: double[] Main.$noinline$test05(int) load_store_elimination (before) 216 /// CHECK: VecStore 217 /// CHECK: VecLoad 218 /// CHECK: VecStore 219 /// CHECK: VecStore 220 /// CHECK: Add 221 /// CHECK: Goto loop:{{B\d+}} 222 223 /// CHECK-START-ARM64: double[] Main.$noinline$test05(int) load_store_elimination (after) 224 /// CHECK: VecStore 225 /// CHECK: VecStore 226 /// CHECK: Add 227 /// CHECK: Goto loop:{{B\d+}} 228 // 229 /// CHECK-NOT: VecStore 230 // 231 // TODO: reenable LSE for graphs with Predicated SIMD. $noinline$test05(int n)232 static double[] $noinline$test05(int n) { 233 double a[] = new double[n]; 234 double b[] = new double[n]; 235 236 // The following loop is vectorized. 237 for (int i = 0; i < n; ++i) { 238 a[i] = 1; 239 b[i] = a[i]; 240 a[i] = 1; 241 } 242 243 return b; 244 } 245 test05()246 static void test05() { 247 double norma = $noinline$test05(128)[0]; 248 System.out.println((int)norma); 249 } 250 251 // Check LSE eliminates VecLoad and ArrayGet in case of singletons and default values. 252 // 253 /// CHECK-START-ARM64: double[] Main.$noinline$test06(int) load_store_elimination (before) 254 /// CHECK: BoundsCheck loop:none 255 /// CHECK: ArrayGet 256 /// CHECK: Add 257 // 258 /// CHECK: VecLoad loop:{{B\d+}} 259 /// CHECK: VecStore 260 /// CHECK: VecLoad 261 /// CHECK: VecLoad 262 /// CHECK: VecAdd 263 /// CHECK: VecAdd 264 /// CHECK: VecStore 265 266 /// CHECK-START-ARM64: double[] Main.$noinline$test06(int) load_store_elimination (after) 267 /// CHECK: BoundsCheck loop:none 268 /// CHECK: Add 269 // 270 /// CHECK: VecLoad loop:{{B\d+}} 271 /// CHECK: VecAdd 272 /// CHECK: VecAdd 273 /// CHECK: VecStore 274 // 275 /// CHECK-IF: not (hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true') 276 // 277 /// CHECK-NOT: VecStore 278 // 279 /// CHECK-FI: 280 // 281 // TODO: reenable LSE for graphs with Predicated SIMD. $noinline$test06(int n)282 static double[] $noinline$test06(int n) { 283 double a[] = new double[n]; 284 double b[] = new double[n]; 285 286 double r = a[0] + 1.0; // ArrayGet:a[0] is eliminated and default 0.0 is used. 287 // The following loop is vectorized. 288 for (int i = 0; i < n; ++i) { 289 b[i] = a[i]; // VecLoad:a[i] is not eliminated. 290 b[i] += a[i] + r; // VecLoad:a[i] and VecLoad:b[i] are eliminated. 291 } 292 293 return b; 294 } 295 test06()296 static void test06() { 297 double norma = $noinline$test06(128)[0]; 298 System.out.println((int)norma); 299 } 300 main(String[] args)301 public static void main(String[] args) { 302 test01(); 303 test02(); 304 test03(); 305 test04(); 306 test05(); 307 test06(); 308 } 309 } 310 311