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