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