Skip to content

Commit

Permalink
8280120: [IR Framework] Add attribute to @ir to enable/disable IR mat…
Browse files Browse the repository at this point in the history
…ching based on the architecture

Reviewed-by: rcastanedalo, epeter, thartmann
  • Loading branch information
danielogh authored and eme64 committed Oct 4, 2023
1 parent 9718f49 commit a8549b6
Show file tree
Hide file tree
Showing 6 changed files with 284 additions and 5 deletions.
27 changes: 24 additions & 3 deletions test/hotspot/jtreg/compiler/lib/ir_framework/IR.java
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,44 @@
*/
String[] applyIf() default {};

/**
* Accepts a single pair composed of a platform string followed by a true/false
* value where a true value necessitates that we are currently testing on that platform and vice-versa.
* IR checks are enforced only if the specified platform constraint is met.
*/
String[] applyIfPlatform() default {};

/**
* Accepts a list of pairs where each pair is composed of a platform string followed by a true/false
* value where a true value necessitates that we are currently testing on that platform and vice-versa.
* IR checks are enforced only if all the specified platform constraints are met.
*/
String[] applyIfPlatformAnd() default {};

/**
* Accepts a list of pairs where each pair is composed of a platform string followed by a true/false
* value where a true value necessitates that we are currently testing on that platform and vice-versa.
* IR checks are enforced if any of the specified platform constraints are met.
*/
String[] applyIfPlatformOr() 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.
* value where a true value necessitates 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.
* value where a true value necessitates 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.
* value where a true value necessitates existence of target feature and vice-versa.
* IR verifications checks are enforced if any of the specified feature constraint is met.
*/
String[] applyIfCPUFeatureOr() default {};
Expand Down
5 changes: 5 additions & 0 deletions test/hotspot/jtreg/compiler/lib/ir_framework/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ Sometimes, an `@IR` rule should only be applied if a certain CPU feature is pres

If a `@Test` annotated method has multiple preconditions (for example `applyIf` and `applyIfCPUFeature`), they are evaluated as a logical conjunction. It's worth noting that flags in `applyIf` are checked only if the CPU features in `applyIfCPUFeature` are matched when they are both specified. This avoids the VM flag being evaluated on hardware that does not support it. An example with both `applyIfCPUFeatureXXX` and `applyIfXXX` can be found in [TestPreconditions](../../../testlibrary_tests/ir_framework/tests/TestPreconditions.java) (internal framework test).

#### Disable/Enable IR Rules based on Platform
`@IR` rules based on the platform can be specified using `applyIfPlatformXXX` in [@IR](./IR.java). A reference for using these attributes can be found in [TestPlatformChecks](../../../testlibrary_tests/ir_framework/tests/TestPlatformChecks.java) (internal framework test).

Platform attributes are evaluated as a logical conjunction, and take precedence over VM Flag attributes. An example with both `applyIfPlatformXXX` and `applyIfXXX` can be found in [TestPreconditions](../../../testlibrary_tests/ir_framework/tests/TestPreconditions.java) (internal framework test).

#### Implicitly Skipping IR Verification
An IR verification cannot always be performed. Certain VM flags explicitly disable IR verification, change the IR shape in unexpected ways letting IR rules fail or even make IR verification impossible:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import compiler.lib.ir_framework.IRNode;
import compiler.lib.ir_framework.TestFramework;
import compiler.lib.ir_framework.shared.*;
import jdk.test.lib.Platform;
import jdk.test.whitebox.WhiteBox;

import java.lang.reflect.Method;
Expand Down Expand Up @@ -55,6 +56,27 @@ public class IREncodingPrinter {
private Method method;
private int ruleIndex;

// Platforms for use in IR preconditions. Please verify that e.g. there is
// a corresponding use in a jtreg @requires annotation before adding new platforms,
// as adding non-existent platforms can lead to skipped tests.
private static final List<String> irTestingPlatforms = new ArrayList<String>(Arrays.asList(
// os.family
"linux",
"mac",
"windows",
// vm.simpleArch
"aarch64",
"arm",
"ppc",
"riscv64",
"s390",
"x64",
"x86",
// corresponds to vm.bits
"32-bit",
"64-bit"
));

// Please verify new CPU features before adding them. If we allow non-existent features
// on this list, we will ignore tests and never execute them. Consult CPU_FEATURE_FLAGS
// in corresponding vm_version_.hpp file to find correct cpu feature's name.
Expand Down Expand Up @@ -132,6 +154,15 @@ private boolean shouldApplyIrRule(IR irAnno, String m, int ruleIndex, int ruleMa
checkIRAnnotations(irAnno);
if (isIRNodeUnsupported(irAnno)) {
return false;
} else if (irAnno.applyIfPlatform().length != 0 && !hasAllRequiredPlatform(irAnno.applyIfPlatform())) {
printDisableReason(m, "Constraint not met (applyIfPlatform)", irAnno.applyIfPlatform(), ruleIndex, ruleMax);
return false;
} else if (irAnno.applyIfPlatformAnd().length != 0 && !hasAllRequiredPlatform(irAnno.applyIfPlatformAnd())) {
printDisableReason(m, "Not all constraints are met (applyIfPlatformAnd)", irAnno.applyIfPlatformAnd(), ruleIndex, ruleMax);
return false;
} else if (irAnno.applyIfPlatformOr().length != 0 && !hasAnyRequiredPlatform(irAnno.applyIfPlatformOr())) {
printDisableReason(m, "None of the constraints are met (applyIfPlatformOr)", irAnno.applyIfPlatformOr(), ruleIndex, ruleMax);
return false;
} else if (irAnno.applyIfCPUFeature().length != 0 && !hasAllRequiredCPUFeature(irAnno.applyIfCPUFeature())) {
printDisableReason(m, "Feature constraint not met (applyIfCPUFeature)", irAnno.applyIfCPUFeature(), ruleIndex, ruleMax);
return false;
Expand Down Expand Up @@ -163,6 +194,7 @@ private void checkIRAnnotations(IR irAnno) {
TestFormat.checkNoThrow(irAnno.counts().length != 0 || irAnno.failOn().length != 0,
"Must specify either counts or failOn constraint" + failAt());
int flagConstraints = 0;
int platformConstraints = 0;
int cpuFeatureConstraints = 0;
if (irAnno.applyIfAnd().length != 0) {
flagConstraints++;
Expand All @@ -179,6 +211,21 @@ private void checkIRAnnotations(IR irAnno) {
TestFormat.checkNoThrow(irAnno.applyIf().length <= 2,
"Use applyIfAnd or applyIfOr or only 1 condition for applyIf" + failAt());
}
if (irAnno.applyIfPlatform().length != 0) {
platformConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfPlatform().length == 2,
"applyIfPlatform expects single platform pair" + failAt());
}
if (irAnno.applyIfPlatformAnd().length != 0) {
platformConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfPlatformAnd().length % 2 == 0,
"applyIfPlatformAnd expects more than one platform pair" + failAt());
}
if (irAnno.applyIfPlatformOr().length != 0) {
platformConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfPlatformOr().length % 2 == 0,
"applyIfPlatformOr expects more than one platform pair" + failAt());
}
if (irAnno.applyIfCPUFeature().length != 0) {
cpuFeatureConstraints++;
TestFormat.checkNoThrow(irAnno.applyIfCPUFeature().length == 2,
Expand All @@ -200,6 +247,7 @@ private void checkIRAnnotations(IR irAnno) {
"Use applyIfAnd or applyIfOr or only 1 condition for applyIfNot" + failAt());
}
TestFormat.checkNoThrow(flagConstraints <= 1, "Can only specify one flag constraint" + failAt());
TestFormat.checkNoThrow(platformConstraints <= 1, "Can only specify one platform constraint" + failAt());
TestFormat.checkNoThrow(cpuFeatureConstraints <= 1, "Can only specify one CPU feature constraint" + failAt());
}

Expand Down Expand Up @@ -233,6 +281,82 @@ private boolean hasAllRequiredFlags(String[] andRules, String ruleType) {
return returnValue;
}

private boolean hasAllRequiredPlatform(String[] andRules) {
boolean returnValue = true;
for (int i = 0; i < andRules.length; i++) {
String platform = andRules[i].trim();
i++;
String value = andRules[i].trim();
returnValue &= checkPlatform(platform, value);
}
return returnValue;
}

private boolean hasAnyRequiredPlatform(String[] orRules) {
boolean returnValue = false;
for (int i = 0; i < orRules.length; i++) {
String platform = orRules[i].trim();
i++;
String value = orRules[i].trim();
returnValue |= checkPlatform(platform, value);
}
return returnValue;
}

private boolean checkPlatform(String platform, String value) {
if (platform.isEmpty()) {
TestFormat.failNoThrow("Provided empty platform" + failAt());
return false;
}
if (value.isEmpty()) {
TestFormat.failNoThrow("Provided empty value for platform " + platform + failAt());
return false;
}

if (!irTestingPlatforms.contains(platform)) {
TestFormat.failNoThrow("Provided platform is not in verified list: " + platform + failAt());
return false;
}

boolean trueValue = value.contains("true");
boolean falseValue = value.contains("false");

if (!trueValue && !falseValue) {
TestFormat.failNoThrow("Provided incorrect value for platform " + platform + failAt());
return false;
}

String os = "";
if (Platform.isLinux()) {
os = "linux";
} else if (Platform.isOSX()) {
os = "mac";
} else if (Platform.isWindows()) {
os = "windows";
}

String arch = "";
if (Platform.isAArch64()) {
arch = "aarch64";
} else if (Platform.isARM()) {
arch = "arm";
} else if (Platform.isPPC()) {
arch = "ppc";
} else if (Platform.isRISCV64()) {
arch = "riscv64";
} else if (Platform.isS390x()) {
arch = "s390";
} else if (Platform.isX64()) {
arch = "x64";
} else if (Platform.isX86()) {
arch = "x86";
}

String currentPlatform = os + " " + arch + " " + (Platform.is32bit() ? "32-bit" : "64-bit");

return (trueValue && currentPlatform.contains(platform)) || (falseValue && !currentPlatform.contains(platform));
}

private boolean hasAllRequiredCPUFeature(String[] andRules) {
boolean returnValue = true;
for (int i = 0; i < andRules.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
* @test
* @bug 8076276
* @summary Add C2 x86 Superword support for scalar sum reduction optimizations : long test
* @requires vm.bits == "64"
* @library /test/lib /
* @run driver compiler.loopopts.superword.SumRed_Long
*/
Expand Down Expand Up @@ -93,7 +92,8 @@ public static void sumReductionInit(
@Test
@IR(applyIf = {"SuperWordReductions", "false"},
failOn = {IRNode.ADD_REDUCTION_VL})
@IR(applyIfCPUFeature = {"avx2", "true"},
@IR(applyIfPlatform = {"32-bit", "false"},
applyIfCPUFeature = {"avx2", "true"},
applyIfAnd = {"SuperWordReductions", "true", "LoopMaxUnroll", ">= 8"},
counts = {IRNode.ADD_REDUCTION_VL, ">= 1", IRNode.ADD_REDUCTION_VL, "<= 2"}) // one for main-loop, one for vector-post-loop
public static long sumReductionImplement(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2023, 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 ir_framework.tests;

import compiler.lib.ir_framework.*;
import compiler.lib.ir_framework.driver.irmatching.IRViolationException;

/*
* @test 8280120
* @summary Add attribute to IR to enable/disable IR matching based on the architecture
* @library /test/lib /
* @run driver ir_framework.tests.TestPlatformChecks
*/

public class TestPlatformChecks {
private static final int SIZE = 1000;
private static int[] a = new int[SIZE];
private static int[] b = new int[SIZE];
private static int[] res = new int[SIZE];

public static void setup() {
for (int i = 0; i < SIZE; i++) {
a[i] = i;
b[i] = i;
}
}

public static void main(String[] args) {
setup();
TestFramework.run();
}

@Test
@IR(counts = {IRNode.ADD_VI, "> 0"},
applyIfPlatform = {"x64", "true"},
applyIfCPUFeature = {"sse4.1", "true"})
public static void test1() {
for (int i = 0; i < SIZE; i++) {
res[i] = a[i] + b[i];
}
}

// IR rule is enforced if all the platform constraints hold
@Test
@IR(counts = {IRNode.ADD_VI, "> 0"},
applyIfPlatformAnd = {"x64", "true", "linux", "true"},
applyIfCPUFeatureAnd = {"sse4.1", "true", "avx2", "true"})
public static void test2() {
for (int i = 0; i < SIZE; i++) {
res[i] = a[i] + b[i];
}
}

// IR rule is enforced if any of the platform constraints hold
@Test
@IR(counts = {IRNode.ADD_VI, "> 0"},
applyIfPlatformOr = {"linux", "true", "mac", "true"},
applyIfCPUFeatureOr = {"sse4.1", "true", "avx2", "true"})
public static void test3() {
for (int i = 0; i < SIZE; i++) {
res[i] = a[i] + b[i];
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,48 @@ public static void testApplyBoth2() {}
applyIfAnd = {"UseAVX", "= 2", "LoopMaxUnroll", "= 0"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyBoth3() {}

// The IR check should not be applied, since OS can not be both linux and mac.
@Test
@IR(applyIfPlatformAnd = {"linux", "true", "mac", "true"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyBothOs() {}

// The IR check should not be applied, since we can't have both 32-bit and 64-bit data model.
@Test
@IR(applyIfPlatformAnd = {"32-bit", "true", "64-bit", "true"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyBothDataModel() {}

// The IR check should not be applied, since the arch can't be both x64 and aarch64.
@Test
@IR(applyIfPlatformAnd = {"x64", "true", "aarch64", "true"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyBothArch() {}

// Platform versions of testApplyBoth2/3.
@Test
@IR(applyIfPlatform = {"aarch64", "true"},
applyIfAnd = {"UseSVE", "= 0", "LoopMaxUnroll", "= 0"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyPlatformSVE() {}

@Test
@IR(applyIfPlatform = {"x64", "true"},
applyIfAnd = {"UseAVX", "= 2", "LoopMaxUnroll", "= 0"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyPlatformAVX() {}

@Test
@IR(applyIfPlatformAnd = {"x64", "true", "linux", "true"},
applyIfAnd = {"UseAVX", "= 2", "LoopMaxUnroll", "= 0"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyPlatformAVXAnd() {}

@Test
@IR(applyIfPlatformOr = {"x64", "true", "x86", "true"},
applyIfAnd = {"UseSSE", "= 4", "LoopMaxUnroll", "= 0"},
counts = {IRNode.LOOP, ">= 1000"})
public static void testApplyPlatformSSEOr() {}

}

1 comment on commit a8549b6

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.