1 /*
2 * Copyright (c) 2014, 2024, 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 package compiler.intrinsics.bmi;
25
26 import jdk.test.lib.Asserts;
27 import jdk.test.lib.process.OutputAnalyzer;
28 import jdk.test.lib.process.ProcessTools;
29 import jdk.test.lib.Utils;
30
31 import java.io.IOException;
32 import java.nio.file.Files;
33 import java.nio.file.Paths;
34 import java.util.Collections;
35 import java.util.LinkedList;
36 import java.util.List;
37 import 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 */
45 public 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 * </ul>
63 *
64 * @param expr operation that should be tested
65 * @param testOpts options to control test behaviour
66 * @param additionalVMOpts additional options for VM
67 *
68 * @throws Throwable if test failed.
69 */
70 public static void runTests(Class<? extends Expr> expr,
71 String testOpts[],
72 String... additionalVMOpts)
73 throws Throwable {
74
75 // ensure seed got printed out
76 Utils.getRandomInstance();
77 long seed = Utils.SEED;
78 int iterations = DEFAULT_ITERATIONS_COUNT;
79
80 for (String testOption : testOpts) {
81 if (testOption.startsWith("-iterations=")) {
82 iterations = Integer.valueOf(testOption.
83 replace("-iterations=", ""));
84 }
85 }
86
87 OutputAnalyzer intOutput = runTest(expr, VMMode.INT,
88 additionalVMOpts,
89 seed, iterations);
90 OutputAnalyzer compOutput = runTest(expr, VMMode.COMP,
91 additionalVMOpts,
92 seed, iterations);
93
94 dumpOutput(intOutput, "int");
95 dumpOutput(compOutput, "comp");
96
97 Asserts.assertStringsEqual(intOutput.getStdout(),
98 compOutput.getStdout(),
99 "Results obtained in -Xint and " +
100 "-Xcomp should be the same.");
101 }
102
103 /**
104 * Execute tests on methods implemented by <b>expr</b> in new VM
105 * started in <b>testVMMode</b> mode.
106 *
107 * @param expr operation that should be tested
108 * @param testVMMode VM mode for test
109 * @param additionalVMOpts additional options for VM
110 * @param seed for RNG used it tests
111 * @param iterations that will be used to invoke <b>expr</b>'s methods.
112 *
113 * @return OutputAnalyzer for executed test.
114 * @throws Throwable when something goes wrong.
115 */
116 public static OutputAnalyzer runTest(Class<? extends Expr> expr,
117 VMMode testVMMode,
118 String additionalVMOpts[],
119 long seed, int iterations)
120 throws Throwable {
121
122 List<String> vmOpts = new LinkedList<String>();
123
124 Collections.addAll(vmOpts, additionalVMOpts);
125 // Hide timestamps from warnings (e.g. due to potential AOT
126 // saved/runtime state mismatch), to avoid false positives when
127 // comparing output across runs.
128 vmOpts.add("-Xlog:all=warning:stdout:level,tags");
129 vmOpts.add("-Xlog:aot=off");
130
131 //setup mode-specific options
132 switch (testVMMode) {
133 case INT:
134 Collections.addAll(vmOpts, new String[] { "-Xint" });
135 break;
136 case COMP:
137 Collections.addAll(vmOpts, new String[] {
138 "-Xcomp",
139 "-XX:-TieredCompilation",
140 String.format("-XX:CompileCommand=compileonly,%s::*",
141 expr.getName())
142 });
143 break;
144 }
145
146 Collections.addAll(vmOpts, new String[] {
147 "-XX:+DisplayVMOutputToStderr",
148 "-D" + Utils.SEED_PROPERTY_NAME + "=" + seed,
149 Executor.class.getName(),
150 expr.getName(),
151 new Integer(iterations).toString()
152 });
153
154 OutputAnalyzer outputAnalyzer = ProcessTools.executeTestJava(vmOpts);
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 runUnaryIntToLongRegTest(expr, iterations, rng);
227 runBinaryRegRegIntTest(expr, iterations, rng);
228 runBinaryRegMemIntTest(expr, iterations, rng);
229 runBinaryMemRegIntTest(expr, iterations, rng);
230 runBinaryMemMemIntTest(expr, iterations, rng);
231 runBinaryRegRegLongTest(expr, iterations, rng);
232 runBinaryRegMemLongTest(expr, iterations, rng);
233 runBinaryMemRegLongTest(expr, iterations, rng);
234 runBinaryMemMemLongTest(expr, iterations, rng);
235 }
236
237 public static void runUnaryIntRegTest(Expr expr, int iterations,
238 Random rng) {
239 if (!(expr.isUnaryArgumentSupported()
240 && expr.isIntExprSupported())) {
241 return;
242 }
243
244 for (int value : getIntBitShifts()) {
245 log("UnaryIntReg(0X%x) -> 0X%x",
246 value, expr.intExpr(value));
247 }
248
249 for (int i = 0; i < iterations; i++) {
250 int value = rng.nextInt();
251 log("UnaryIntReg(0X%x) -> 0X%x",
252 value, expr.intExpr(value));
253 }
254 }
255
256 public static void runUnaryIntMemTest(Expr expr, int iterations,
257 Random rng) {
258 if (!(expr.isUnaryArgumentSupported()
259 && expr.isIntExprSupported()
260 && expr.isMemExprSupported())) {
261 return;
262 }
263
264 for (int value : getIntBitShifts()) {
265 log("UnaryIntMem(0X%x) -> 0X%x",
266 value, expr.intExpr(new Expr.MemI(value)));
267 }
268
269 for (int i = 0; i < iterations; i++) {
270 int value = rng.nextInt();
271 log("UnaryIntMem(0X%x) -> 0X%x",
272 value, expr.intExpr(new Expr.MemI(value)));
273 }
274 }
275
276 public static void runUnaryLongRegTest(Expr expr, int iterations,
277 Random rng) {
278 if (!(expr.isUnaryArgumentSupported()
279 && expr.isLongExprSupported())) {
280 return;
281 }
282
283 for (long value : getLongBitShifts()) {
284 log("UnaryLongReg(0X%x) -> 0X%x",
285 value, expr.longExpr(value));
286 }
287
288 for (int i = 0; i < iterations; i++) {
289 long value = rng.nextLong();
290 log("UnaryLongReg(0X%x) -> 0X%x",
291 value, expr.longExpr(value));
292 }
293 }
294
295 public static void runUnaryLongMemTest(Expr expr, int iterations,
296 Random rng) {
297 if (!(expr.isUnaryArgumentSupported()
298 && expr.isLongExprSupported()
299 && expr.isMemExprSupported())) {
300 return;
301 }
302
303 for (long value : getLongBitShifts()) {
304 log("UnaryLongMem(0X%x) -> 0X%x",
305 value, expr.longExpr(new Expr.MemL(value)));
306 }
307
308 for (int i = 0; i < iterations; i++) {
309 long value = rng.nextLong();
310 log("UnaryLongMem(0X%x) -> 0X%x",
311 value, expr.longExpr(new Expr.MemL(value)));
312 }
313 }
314
315 public static void runUnaryIntToLongRegTest(Expr expr, int iterations,
316 Random rng) {
317 if (!(expr.isUnaryArgumentSupported()
318 && expr.isIntToLongExprSupported())) {
319 return;
320 }
321
322 for (int value : getIntBitShifts()) {
323 log("UnaryIntToLongReg(0X%x) -> 0X%x",
324 value, expr.intToLongExpr(value));
325 }
326
327 for (int i = 0; i < iterations; i++) {
328 int value = rng.nextInt();
329 log("UnaryIntToLongReg(0X%x) -> 0X%x",
330 value, expr.intToLongExpr(value));
331 }
332 }
333
334 public static void runBinaryRegRegIntTest(Expr expr, int iterations,
335 Random rng) {
336 if (!(expr.isIntExprSupported()
337 && expr.isBinaryArgumentSupported())) {
338 return;
339 }
340
341 for (int i = 0; i < iterations; i++) {
342 int aValue = rng.nextInt();
343 int bValue = rng.nextInt();
344 log("BinaryIntRegReg(0X%x, 0X%x) -> 0X%x",
345 aValue, bValue, expr.intExpr(aValue, bValue));
346 }
347 }
348
349 public static void runBinaryRegMemIntTest(Expr expr, int iterations,
350 Random rng) {
351 if (!(expr.isIntExprSupported()
352 && expr.isBinaryArgumentSupported()
353 && expr.isMemExprSupported())) {
354 return;
355 }
356
357 for (int i = 0; i < iterations; i++) {
358 int aValue = rng.nextInt();
359 int bValue = rng.nextInt();
360 log("BinaryIntRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
361 expr.intExpr(aValue, new Expr.MemI(bValue)));
362 }
363 }
364
365 public static void runBinaryMemRegIntTest(Expr expr, int iterations,
366 Random rng) {
367 if (!(expr.isIntExprSupported()
368 && expr.isBinaryArgumentSupported()
369 && expr.isMemExprSupported())) {
370 return;
371 }
372
373 for (int i = 0; i < iterations; i++) {
374 int aValue = rng.nextInt();
375 int bValue = rng.nextInt();
376 log("BinaryIntMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue,
377 expr.intExpr(new Expr.MemI(aValue), bValue));
378 }
379 }
380
381 public static void runBinaryMemMemIntTest(Expr expr, int iterations,
382 Random rng) {
383 if (!(expr.isIntExprSupported()
384 && expr.isBinaryArgumentSupported()
385 && expr.isMemExprSupported())) {
386 return;
387 }
388
389 for (int i = 0; i < iterations; i++) {
390 int aValue = rng.nextInt();
391 int bValue = rng.nextInt();
392 log("BinaryIntMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
393 expr.intExpr(new Expr.MemI(aValue),
394 new Expr.MemI(bValue)));
395 }
396 }
397
398 public static void runBinaryRegRegLongTest(Expr expr,
399 int iterations,
400 Random rng) {
401 if (!(expr.isLongExprSupported()
402 && expr.isBinaryArgumentSupported())) {
403 return;
404 }
405
406 for (int i = 0; i < iterations; i++) {
407 long aValue = rng.nextLong();
408 long bValue = rng.nextLong();
409 log("BinaryLongRegReg(0X%x, 0X%x) -> 0X%x", aValue, bValue,
410 expr.longExpr(aValue, bValue));
411 }
412 }
413
414 public static void runBinaryRegMemLongTest(Expr expr,
415 int iterations,
416 Random rng) {
417 if (!(expr.isLongExprSupported()
418 && expr.isBinaryArgumentSupported()
419 && expr.isMemExprSupported())) {
420 return;
421 }
422
423 for (int i = 0; i < iterations; i++) {
424 long aValue = rng.nextLong();
425 long bValue = rng.nextLong();
426 log("BinaryLongRegMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
427 expr.longExpr(aValue, new Expr.MemL(bValue)));
428 }
429 }
430
431 public static void runBinaryMemRegLongTest(Expr expr,
432 int iterations,
433 Random rng) {
434 if (!(expr.isLongExprSupported()
435 && expr.isBinaryArgumentSupported()
436 && expr.isMemExprSupported())) {
437 return;
438 }
439
440 for (int i = 0; i < iterations; i++) {
441 long aValue = rng.nextLong();
442 long bValue = rng.nextLong();
443 log("BinaryLongMemReg(0X%x, 0X%x) -> 0X%x", aValue, bValue,
444 expr.longExpr(new Expr.MemL(aValue), bValue));
445 }
446 }
447
448 public static void runBinaryMemMemLongTest(Expr expr,
449 int iterations,
450 Random rng) {
451 if (!(expr.isLongExprSupported()
452 && expr.isBinaryArgumentSupported()
453 && expr.isMemExprSupported())) {
454 return;
455 }
456
457 for (int i = 0; i < iterations; i++) {
458 long aValue = rng.nextLong();
459 long bValue = rng.nextLong();
460 log("BinaryLongMemMem(0X%x, 0X%x) -> 0X%x", aValue, bValue,
461 expr.longExpr(new Expr.MemL(aValue),
462 new Expr.MemL(bValue)));
463 }
464 }
465 }
466 }
--- EOF ---