1 /* 2 * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 package compiler.intrinsics.bmi; 26 27 import jdk.test.lib.Asserts; 28 import jdk.test.lib.process.OutputAnalyzer; 29 import jdk.test.lib.process.ProcessTools; 30 import jdk.test.lib.Utils; 31 32 import java.io.IOException; 33 import java.nio.file.Files; 34 import java.nio.file.Paths; 35 import java.util.Collections; 36 import java.util.LinkedList; 37 import java.util.List; 38 import java.util.Random; 39 40 /** 41 * Test runner that invokes all methods implemented by particular Expr 42 * with random arguments in two different JVM processes and compares output. 43 * JVMs being started in different modes - one in int and other in comp 44 * with C2 and disabled tiered compilation. 45 */ 46 public class BMITestRunner { 47 48 enum VMMode { 49 COMP, INT; 50 }; 51 52 public static int DEFAULT_ITERATIONS_COUNT = 4000; 53 54 /** 55 * Execute all methods implemented by <b>expr</b> in int and comp modes 56 * and compare output. 57 * Test pass only of output obtained with different VM modes is equal. 58 * To control behaviour of test following options could be passed: 59 * <ul> 60 * <li>-iterations=<N> each operation implemented by 61 * <b>expr</b> will be executed <i>N</i> times. Default value 62 * is 4000.</li> 63 * <li>-seed=<SEED> arguments for <b>expr</b>'s methods 64 * obtained via RNG initiated with seed <i>SEED</i>. By default 65 * some random seed will be used.</li> 66 * </ul> 67 * 68 * @param expr operation that should be tested 69 * @param testOpts options to control test behaviour 70 * @param additionalVMOpts additional options for VM 71 * 72 * @throws Throwable if test failed. 73 */ 74 public static void runTests(Class<? extends Expr> expr, 75 String testOpts[], 76 String... additionalVMOpts) 77 throws Throwable { 78 79 int seed = Utils.getRandomInstance().nextInt(); 80 int iterations = DEFAULT_ITERATIONS_COUNT; 81 82 for (String testOption : testOpts) { 83 if (testOption.startsWith("-iterations=")) { 84 iterations = Integer.valueOf(testOption. 85 replace("-iterations=", "")); 86 } else if (testOption.startsWith("-seed=")) { 87 seed = Integer.valueOf(testOption.replace("-seed=", "")); 88 } 89 } 90 91 OutputAnalyzer intOutput = runTest(expr, VMMode.INT, 92 additionalVMOpts, 93 seed, iterations); 94 OutputAnalyzer compOutput = runTest(expr, VMMode.COMP, 95 additionalVMOpts, 96 seed, iterations); 97 98 dumpOutput(intOutput, "int"); 99 dumpOutput(compOutput, "comp"); 100 101 Asserts.assertStringsEqual(intOutput.getStdout(), 102 compOutput.getStdout(), 103 "Results obtained in -Xint and " + 104 "-Xcomp should be the same."); 105 } 106 107 /** 108 * Execute tests on methods implemented by <b>expr</b> in new VM 109 * started in <b>testVMMode</b> mode. 110 * 111 * @param expr operation that should be tested 112 * @param testVMMode VM mode for test 113 * @param additionalVMOpts additional options for VM 114 * @param seed for RNG used it tests 115 * @param iterations that will be used to invoke <b>expr</b>'s methods. 116 * 117 * @return OutputAnalyzer for executed test. 118 * @throws Throwable when something goes wrong. 119 */ 120 public static OutputAnalyzer runTest(Class<? extends Expr> expr, 121 VMMode testVMMode, 122 String additionalVMOpts[], 123 int seed, int iterations) 124 throws Throwable { 125 126 List<String> vmOpts = new LinkedList<String>(); 127 128 Collections.addAll(vmOpts, additionalVMOpts); 129 130 //setup mode-specific options 131 switch (testVMMode) { 132 case INT: 133 Collections.addAll(vmOpts, new String[] { "-Xint" }); 134 break; 135 case COMP: 136 Collections.addAll(vmOpts, new String[] { 137 "-Xcomp", 138 "-XX:-TieredCompilation", 139 String.format("-XX:CompileCommand=compileonly,%s::*", 140 expr.getName()) 141 }); 142 break; 143 } 144 145 Collections.addAll(vmOpts, new String[] { 146 "-XX:+DisplayVMOutputToStderr", 147 "-D" + Utils.SEED_PROPERTY_NAME + "=" + seed, 148 Executor.class.getName(), 149 expr.getName(), 150 new Integer(iterations).toString() 151 }); 152 153 OutputAnalyzer outputAnalyzer = ProcessTools. 154 executeTestJvm(vmOpts.toArray(new String[vmOpts.size()])); 155 156 outputAnalyzer.shouldHaveExitValue(0); 157 158 return outputAnalyzer; 159 } 160 161 /** 162 * Dump stdout and stderr of test process to <i>prefix</i>.test.out 163 * and <i>prefix</i>.test.err respectively. 164 * 165 * @param outputAnalyzer OutputAnalyzer whom output should be dumped 166 * @param prefix Prefix that will be used in file names. 167 * @throws IOException if unable to dump output to file. 168 */ 169 protected static void dumpOutput(OutputAnalyzer outputAnalyzer, 170 String prefix) 171 throws IOException { 172 Files.write(Paths.get(prefix + ".test.out"), 173 outputAnalyzer.getStdout().getBytes()); 174 175 Files.write(Paths.get(prefix + ".test.err"), 176 outputAnalyzer.getStderr().getBytes()); 177 } 178 179 180 /** 181 * Executor that invoke all methods implemented by particular 182 * Expr instance. 183 */ 184 public static class Executor { 185 186 /** 187 * Usage: BMITestRunner$Executor <ExprClassName> <iterations> 188 */ 189 public static void main(String args[]) throws Exception { 190 @SuppressWarnings("unchecked") 191 Class<? extends Expr> exprClass = 192 (Class<? extends Expr>)Class.forName(args[0]); 193 Expr expr = exprClass.getConstructor().newInstance(); 194 int iterations = Integer.valueOf(args[1]); 195 runTests(expr, iterations, Utils.getRandomInstance()); 196 } 197 198 199 public static int[] getIntBitShifts() { 200 //SIZE+1 shift is for zero. 201 int data[] = new int[Integer.SIZE+1]; 202 for (int s = 0; s < data.length; s++) { 203 data[s] = 1<<s; 204 } 205 return data; 206 } 207 208 public static long[] getLongBitShifts() { 209 //SIZE+1 shift is for zero. 210 long data[] = new long[Long.SIZE+1]; 211 for (int s = 0; s < data.length; s++) { 212 data[s] = 1L<<s; 213 } 214 return data; 215 } 216 217 public static void log(String format, Object... args) { 218 System.out.println(String.format(format, args)); 219 } 220 221 public static void runTests(Expr expr, int iterations, Random rng) { 222 runUnaryIntRegTest(expr, iterations, rng); 223 runUnaryIntMemTest(expr, iterations, rng); 224 runUnaryLongRegTest(expr, iterations, rng); 225 runUnaryLongMemTest(expr, iterations, rng); 226 runBinaryRegRegIntTest(expr, iterations, rng); 227 runBinaryRegMemIntTest(expr, iterations, rng); 228 runBinaryMemRegIntTest(expr, iterations, rng); 229 runBinaryMemMemIntTest(expr, iterations, rng); 230 runBinaryRegRegLongTest(expr, iterations, rng); 231 runBinaryRegMemLongTest(expr, iterations, rng); 232 runBinaryMemRegLongTest(expr, iterations, rng); 233 runBinaryMemMemLongTest(expr, iterations, rng); 234 } 235 236 public static void runUnaryIntRegTest(Expr expr, int iterations, 237 Random rng) { 238 if (!(expr.isUnaryArgumentSupported() 239 && expr.isIntExprSupported())) { 240 return; 241 } 242 243 for (int value : getIntBitShifts()) { 244 log("UnaryIntReg(0X%x) -> 0X%x", 245 value, expr.intExpr(value)); 246 } 247 248 for (int i = 0; i < iterations; i++) { 249 int value = rng.nextInt(); 250 log("UnaryIntReg(0X%x) -> 0X%x", 251 value, expr.intExpr(value)); 252 } 253 } 254 255 public static void runUnaryIntMemTest(Expr expr, int iterations, 256 Random rng) { 257 if (!(expr.isUnaryArgumentSupported() 258 && expr.isIntExprSupported() 259 && expr.isMemExprSupported())) { 260 return; 261 } 262 263 for (int value : getIntBitShifts()) { 264 log("UnaryIntMem(0X%x) -> 0X%x", 265 value, expr.intExpr(new Expr.MemI(value))); 266 } 267 268 for (int i = 0; i < iterations; i++) { 269 int value = rng.nextInt(); 270 log("UnaryIntMem(0X%x) -> 0X%x", 271 value, expr.intExpr(new Expr.MemI(value))); 272 } 273 } 274 275 public static void runUnaryLongRegTest(Expr expr, int iterations, 276 Random rng) { 277 if (!(expr.isUnaryArgumentSupported() 278 && expr.isLongExprSupported())) { 279 return; 280 } 281 282 for (long value : getLongBitShifts()) { 283 log("UnaryLongReg(0X%x) -> 0X%x", 284 value, expr.longExpr(value)); 285 } 286 287 for (int i = 0; i < iterations; i++) { 288 long value = rng.nextLong(); 289 log("UnaryLongReg(0X%x) -> 0X%x", 290 value, expr.longExpr(value)); 291 } 292 } 293 294 public static void runUnaryLongMemTest(Expr expr, int iterations, 295 Random rng) { 296 if (!(expr.isUnaryArgumentSupported() 297 && expr.isLongExprSupported() 298 && expr.isMemExprSupported())) { 299 return; 300 } 301 302 for (long value : getLongBitShifts()) { 303 log("UnaryLongMem(0X%x) -> 0X%x", 304 value, expr.longExpr(new Expr.MemL(value))); 305 } 306 307 for (int i = 0; i < iterations; i++) { 308 long value = rng.nextLong(); 309 log("UnaryLongMem(0X%x) -> 0X%x", 310 value, expr.longExpr(new Expr.MemL(value))); 311 } 312 } 313 314 public static void runBinaryRegRegIntTest(Expr expr, int iterations, 315 Random rng) { 316 if (!(expr.isIntExprSupported() 317 && expr.isBinaryArgumentSupported())) { 318 return; 319 } 320 321 for (int i = 0; i < iterations; i++) { 322 int aValue = rng.nextInt(); 323 int bValue = rng.nextInt(); 324 log("BinaryIntRegReg(0X%x, 0X%x) -> 0X%x", 325 aValue, bValue, expr.intExpr(aValue, bValue)); 326 } 327 } 328 329 public static void runBinaryRegMemIntTest(Expr expr, int iterations, 330 Random rng) { 331 if (!(expr.isIntExprSupported() 332 && expr.isBinaryArgumentSupported() 333 && expr.isMemExprSupported())) { 334 return; 335 } 336 337 for (int i = 0; i < iterations; i++) { 338 int aValue = rng.nextInt(); 339 int bValue = rng.nextInt(); 340 log("BinaryIntRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 341 expr.intExpr(aValue, new Expr.MemI(bValue))); 342 } 343 } 344 345 public static void runBinaryMemRegIntTest(Expr expr, int iterations, 346 Random rng) { 347 if (!(expr.isIntExprSupported() 348 && expr.isBinaryArgumentSupported() 349 && expr.isMemExprSupported())) { 350 return; 351 } 352 353 for (int i = 0; i < iterations; i++) { 354 int aValue = rng.nextInt(); 355 int bValue = rng.nextInt(); 356 log("BinaryIntMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, 357 expr.intExpr(new Expr.MemI(aValue), bValue)); 358 } 359 } 360 361 public static void runBinaryMemMemIntTest(Expr expr, int iterations, 362 Random rng) { 363 if (!(expr.isIntExprSupported() 364 && expr.isBinaryArgumentSupported() 365 && expr.isMemExprSupported())) { 366 return; 367 } 368 369 for (int i = 0; i < iterations; i++) { 370 int aValue = rng.nextInt(); 371 int bValue = rng.nextInt(); 372 log("BinaryIntMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 373 expr.intExpr(new Expr.MemI(aValue), 374 new Expr.MemI(bValue))); 375 } 376 } 377 378 public static void runBinaryRegRegLongTest(Expr expr, 379 int iterations, 380 Random rng) { 381 if (!(expr.isLongExprSupported() 382 && expr.isBinaryArgumentSupported())) { 383 return; 384 } 385 386 for (int i = 0; i < iterations; i++) { 387 long aValue = rng.nextLong(); 388 long bValue = rng.nextLong(); 389 log("BinaryLongRegReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, 390 expr.longExpr(aValue, bValue)); 391 } 392 } 393 394 public static void runBinaryRegMemLongTest(Expr expr, 395 int iterations, 396 Random rng) { 397 if (!(expr.isLongExprSupported() 398 && expr.isBinaryArgumentSupported() 399 && expr.isMemExprSupported())) { 400 return; 401 } 402 403 for (int i = 0; i < iterations; i++) { 404 long aValue = rng.nextLong(); 405 long bValue = rng.nextLong(); 406 log("BinaryLongRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 407 expr.longExpr(aValue, new Expr.MemL(bValue))); 408 } 409 } 410 411 public static void runBinaryMemRegLongTest(Expr expr, 412 int iterations, 413 Random rng) { 414 if (!(expr.isLongExprSupported() 415 && expr.isBinaryArgumentSupported() 416 && expr.isMemExprSupported())) { 417 return; 418 } 419 420 for (int i = 0; i < iterations; i++) { 421 long aValue = rng.nextLong(); 422 long bValue = rng.nextLong(); 423 log("BinaryLongMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue, 424 expr.longExpr(new Expr.MemL(aValue), bValue)); 425 } 426 } 427 428 public static void runBinaryMemMemLongTest(Expr expr, 429 int iterations, 430 Random rng) { 431 if (!(expr.isLongExprSupported() 432 && expr.isBinaryArgumentSupported() 433 && expr.isMemExprSupported())) { 434 return; 435 } 436 437 for (int i = 0; i < iterations; i++) { 438 long aValue = rng.nextLong(); 439 long bValue = rng.nextLong(); 440 log("BinaryLongMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue, 441 expr.longExpr(new Expr.MemL(aValue), 442 new Expr.MemL(bValue))); 443 } 444 } 445 } 446 }