8287525: Extend IR annotation with new options to test specific target feature.

Co-authored-by: Jatin Bhateja <jbhateja@openjdk.org>
Reviewed-by: chagedorn, kvn
This commit is contained in:
Swati Sharma 2022-06-14 06:13:26 +00:00 committed by Jatin Bhateja
parent 86c9241cce
commit 03dca565cf
5 changed files with 250 additions and 13 deletions

View File

@ -938,6 +938,8 @@ void VM_Version::get_processor_features() {
_features &= ~CPU_HT;
}
// Note: Any modifications to following suppressed feature list for KNL target
// should also be applied to test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java
if (is_intel()) { // Intel cpus specific settings
if (is_knights_family()) {
_features &= ~CPU_VZEROUPPER;

View File

@ -98,6 +98,27 @@ public @interface IR {
*/
String[] applyIf() default {};
/**
* Accepts a single feature pair which is composed of CPU feature string followed by a true/false
* value where a true value necessities existence of CPU feature and vice-versa.
* IR verifications checks are enforced only if the specified feature constraint is met.
*/
String[] applyIfCPUFeature() default {};
/**
* Accepts a list of feature pairs where each pair is composed of target feature string followed by a true/false
* value where a true value necessities existence of target feature and vice-versa.
* IR verifications checks are enforced only if all the specified feature constraints are met.
*/
String[] applyIfCPUFeatureAnd() default {};
/**
* Accepts a list of feature pairs where each pair is composed of target feature string followed by a true/false
* value where a true value necessities existence of target feature and vice-versa.
* IR verifications checks are enforced if any of the specified feature constraint is met.
*/
String[] applyIfCPUFeatureOr() default {};
/**
* Define a single VM flag precondition which <i>must <b>not</b> hold</i> when applying the IR rule. If, however,
* the VM flag precondition holds, then the IR rule is not applied. This could also be defined as <i>negative</i>

View File

@ -166,6 +166,7 @@ public class IRNode {
public static final String ADD_I = START + "AddI" + MID + END;
public static final String ADD_L = START + "AddL" + MID + END;
public static final String ADD_VD = START + "AddVD" + MID + END;
public static final String ADD_VI = START + "AddVI" + MID + END;
public static final String SUB = START + "Sub(I|L|F|D)" + MID + END;
public static final String SUB_I = START + "SubI" + MID + END;
public static final String SUB_L = START + "SubL" + MID + END;

View File

@ -33,6 +33,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.HashSet;
/**
* Prints an encoding to the dedicated test framework socket whether @IR rules of @Test methods should be applied or not.
@ -72,7 +73,7 @@ public class IREncodingPrinter {
for (IR irAnno : irAnnos) {
ruleIndex = i + 1;
try {
if (shouldApplyIrRule(irAnno)) {
if (shouldApplyIrRule(irAnno, m.getName())) {
validRules.add(ruleIndex);
}
} catch (TestFormatException e) {
@ -94,25 +95,72 @@ public class IREncodingPrinter {
}
}
private boolean shouldApplyIrRule(IR irAnno) {
private boolean shouldApplyIrRule(IR irAnno, String m) {
checkIRAnnotations(irAnno);
if (isDefaultRegexUnsupported(irAnno)) {
return false;
}
if (irAnno.applyIf().length != 0) {
return hasAllRequiredFlags(irAnno.applyIf(), "applyIf");
boolean check = hasAllRequiredFlags(irAnno.applyIf(), "applyIf");
if (!check) {
TestFrameworkSocket.write("Disabling IR matching for " + m + ": Flag constraint not met.",
"[IREncodingPrinter]", true);
}
return check;
}
if (irAnno.applyIfNot().length != 0) {
return hasNoRequiredFlags(irAnno.applyIfNot(), "applyIfNot");
boolean check = hasNoRequiredFlags(irAnno.applyIfNot(), "applyIfNot");
if (!check) {
TestFrameworkSocket.write("Disabling IR matching for " + m + ": Flag constraint not met.",
"[IREncodingPrinter]", true);
}
return check;
}
if (irAnno.applyIfAnd().length != 0) {
return hasAllRequiredFlags(irAnno.applyIfAnd(), "applyIfAnd");
boolean check = hasAllRequiredFlags(irAnno.applyIfAnd(), "applyIfAnd");
if (!check) {
TestFrameworkSocket.write("Disabling IR matching for " + m + ": All flag constraints not met.",
"[IREncodingPrinter]", true);
}
return check;
}
if (irAnno.applyIfOr().length != 0) {
return !hasNoRequiredFlags(irAnno.applyIfOr(), "applyIfOr");
boolean check = hasNoRequiredFlags(irAnno.applyIfOr(), "applyIfOr");
if (check) {
TestFrameworkSocket.write("Disabling IR matching for " + m + ": None of the flag constraint met.",
"[IREncodingPrinter]", true);
}
return !check;
}
if (irAnno.applyIfCPUFeature().length != 0) {
boolean check = hasAllRequiredCPUFeature(irAnno.applyIfCPUFeature());
if (!check) {
TestFrameworkSocket.write("Disabling IR matching for " + m + ": Feature constraint not met.",
"[IREncodingPrinter]", true);
}
return check;
}
if (irAnno.applyIfCPUFeatureAnd().length != 0) {
boolean check = hasAllRequiredCPUFeature(irAnno.applyIfCPUFeatureAnd());
if (!check) {
TestFrameworkSocket.write("Disabling IR matching for " + m + ": All feature constraints not met.",
"[IREncodingPrinter]", true);
}
return check;
}
if (irAnno.applyIfCPUFeatureOr().length != 0) {
boolean check = hasAnyRequiredCPUFeature(irAnno.applyIfCPUFeatureOr());
if (!check) {
TestFrameworkSocket.write("Disabling IR matching for " + m + ": None of the feature constraint met.",
"[IREncodingPrinter]", true);
}
return check;
}
// No conditions, always apply.
return true;
@ -121,29 +169,45 @@ public class IREncodingPrinter {
private void checkIRAnnotations(IR irAnno) {
TestFormat.checkNoThrow(irAnno.counts().length != 0 || irAnno.failOn().length != 0,
"Must specify either counts or failOn constraint" + failAt());
int applyRules = 0;
int flagConstraints = 0;
int cpuFeatureConstraints = 0;
if (irAnno.applyIfAnd().length != 0) {
applyRules++;
flagConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfAnd().length > 2,
"Use applyIf or applyIfNot or at least 2 conditions for applyIfAnd" + failAt());
}
if (irAnno.applyIfOr().length != 0) {
applyRules++;
flagConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfOr().length > 2,
"Use applyIf or applyIfNot or at least 2 conditions for applyIfOr" + failAt());
}
if (irAnno.applyIf().length != 0) {
applyRules++;
flagConstraints++;
TestFormat.checkNoThrow(irAnno.applyIf().length <= 2,
"Use applyIfAnd or applyIfOr or only 1 condition for applyIf" + failAt());
}
if (irAnno.applyIfCPUFeature().length != 0) {
cpuFeatureConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfCPUFeature().length == 2,
"applyIfCPUFeature expects single CPU feature pair" + failAt());
}
if (irAnno.applyIfCPUFeatureAnd().length != 0) {
cpuFeatureConstraints++;
TestFormat.checkNoThrow((irAnno.applyIfCPUFeatureAnd().length % 2) == 0 && irAnno.applyIfCPUFeatureAnd().length >= 2,
"applyIfCPUFeatureAnd expects more than one CPU feature pair" + failAt());
}
if (irAnno.applyIfCPUFeatureOr().length != 0) {
cpuFeatureConstraints++;
TestFormat.checkNoThrow((irAnno.applyIfCPUFeatureOr().length % 2) == 0 && irAnno.applyIfCPUFeatureOr().length >= 2,
"applyIfCPUFeatureOr expects more than one CPU feature pair" + failAt());
}
if (irAnno.applyIfNot().length != 0) {
applyRules++;
flagConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfNot().length <= 2,
"Use applyIfAnd or applyIfOr or only 1 condition for applyIfNot" + failAt());
}
TestFormat.checkNoThrow(applyRules <= 1,
"Can only specify one apply constraint " + failAt());
TestFormat.checkNoThrow(flagConstraints <= 1, "Can only specify one flag constraint" + failAt());
TestFormat.checkNoThrow(cpuFeatureConstraints <= 1, "Can only specify one CPU feature constraint" + failAt());
}
private boolean isDefaultRegexUnsupported(IR irAnno) {
@ -176,6 +240,72 @@ public class IREncodingPrinter {
return returnValue;
}
private boolean hasAllRequiredCPUFeature(String[] andRules) {
boolean returnValue = true;
for (int i = 0; i < andRules.length; i++) {
String feature = andRules[i].trim();
i++;
String value = andRules[i].trim();
returnValue &= checkCPUFeature(feature, value);
}
return returnValue;
}
private boolean hasAnyRequiredCPUFeature(String[] orRules) {
boolean returnValue = false;
for (int i = 0; i < orRules.length; i++) {
String feature = orRules[i].trim();
i++;
String value = orRules[i].trim();
returnValue |= checkCPUFeature(feature, value);
}
return returnValue;
}
private boolean checkCPUFeature(String feature, String value) {
if (feature.isEmpty()) {
TestFormat.failNoThrow("Provided empty feature" + failAt());
return false;
}
if (value.isEmpty()) {
TestFormat.failNoThrow("Provided empty value for feature " + feature + failAt());
return false;
}
boolean trueValue = value.contains("true");
boolean falseValue = value.contains("false");
if (!trueValue && !falseValue) {
TestFormat.failNoThrow("Provided incorrect value for feature " + feature + failAt());
return false;
}
String cpuFeatures = WHITE_BOX.getCPUFeatures();
// Following feature list is in sync with suppressed feature list for KNL target.
// Please refer vm_version_x86.cpp for details.
HashSet<String> knlFeatureSet = new HashSet<>();
knlFeatureSet.add("AVX512BW");
knlFeatureSet.add("AVX512VL");
knlFeatureSet.add("AVX512DQ");
knlFeatureSet.add("AVX512_VNNI");
knlFeatureSet.add("AVX512_VAES");
knlFeatureSet.add("AVX512_VPOPCNTDQ");
knlFeatureSet.add("AVX512_VPCLMULQDQ");
knlFeatureSet.add("AVX512_VBMI");
knlFeatureSet.add("AVX512_VBMI2");
knlFeatureSet.add("CLWB");
knlFeatureSet.add("FLUSHOPT");
knlFeatureSet.add("GFNI");
knlFeatureSet.add("AVX512_BITALG");
Boolean isKNLFlagEnabled = WHITE_BOX.getBooleanVMFlag("UseKNLSetting");
// Perform the feature check if UseKNLSetting flag is set to off or if
// feature is supported by KNL target.
if (isKNLFlagEnabled == null ||
(isKNLFlagEnabled && (!knlFeatureSet.contains(feature.toUpperCase()) || falseValue))) {
return (trueValue && cpuFeatures.contains(feature)) || (falseValue && !cpuFeatures.contains(feature));
}
return false;
}
private boolean hasNoRequiredFlags(String[] orRules, String ruleType) {
boolean returnValue = true;
for (int i = 0; i < orRules.length; i++) {

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package compiler.vectorapi;
import compiler.lib.ir_framework.*;
import compiler.lib.ir_framework.driver.irmatching.IRViolationException;
/*
* @test 8287525
* @summary Extend IR annotation with new options to test specific target feature.
* @requires vm.cpu.features ~= ".*avx512f.*"
* @requires os.arch=="amd64" | os.arch=="x86_64"
* @library /test/lib /
* @run driver compiler.vectorapi.TestCPUFeatureCheck
*/
public class TestCPUFeatureCheck {
private static int a[] = new int[1000];
private static int b[] = new int[1000];
private static int res[] = new int[1000];
public static void setup() {
for (int i = 0; i < 1000; i++) {
a[i] = i;
b[i] = i;
}
}
public static void main(String args[]) {
setup();
TestFramework.runWithFlags("-XX:-TieredCompilation",
"-XX:UseAVX=3",
"-XX:+UseKNLSetting",
"-XX:CompileThresholdScaling=0.3");
}
@Test
@IR(counts = {IRNode.ADD_VI, "> 0"}, applyIfCPUFeature = {"avx512bw", "false"})
public static void test1() {
for (int i = 0; i < 1000; i++) {
res[i] = a[i] + b[i];
}
}
// IR rule is enforced if all the feature conditions holds good
@Test
@IR(counts = {IRNode.ADD_VI, "> 0"}, applyIfCPUFeatureAnd = {"avx512bw", "false", "avx512f", "true"})
public static void test2() {
for (int i = 0; i < 1000; i++) {
res[i] = a[i] + b[i];
}
}
// IR rule is enforced if any of the feature condition holds good
@Test
@IR(counts = {IRNode.ADD_VI, "> 0"}, applyIfCPUFeatureOr = {"avx512bw", "true", "avx512f", "true"})
public static void test3() {
for (int i = 0; i < 1000; i++) {
res[i] = a[i] + b[i];
}
}
}