-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[AArch64TargetParser]Fix reconstructFromParsedFeatures ignoring negative features #142236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ive features The `targetFeatureToExtension` function used by reconstructFromParsedFeatures only found positive `+FEATURE` strings, but not negative `-FEATURE` strings. Extend the function to handle both to fix `reconstructFromParsedFeatures`.
CI failures are unrelated to the change. |
I need to remind myself what is the expected behavior. Lemme take a look. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since reconstructFromParsedFeatures
is intended to reconstruct the extensions bitset from the -cc1
command line, I'd like to see an integration test in addition to the TargetParserTests unittest. For example using -cc1
with --print-enabled-extensions
if that is possible.
@llvm/pr-subscribers-clang Author: Matthias Braun (MatzeB) ChangesThe Full diff: https://github.com/llvm/llvm-project/pull/142236.diff 3 Files Affected:
diff --git a/clang/test/CodeGen/aarch64-always-inline-feature-bug.c b/clang/test/CodeGen/aarch64-always-inline-feature-bug.c
new file mode 100644
index 0000000000000..27c3983c66d2b
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-always-inline-feature-bug.c
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple aarch64-- -target-feature +neon -target-feature +sve\
+// RUN: -target-feature -sve -emit-llvm %s -o - | FileCheck %s
+
+// Reproducer for bug where clang would reject always_inline for unrelated
+// target features if they were disable with `-feature` on the command line.
+// CHECK: @bar
+__attribute__((always_inline)) __attribute__((target("neon"))) void foo() {}
+void bar() { foo(); }
diff --git a/llvm/lib/TargetParser/AArch64TargetParser.cpp b/llvm/lib/TargetParser/AArch64TargetParser.cpp
index e13c6e6d28c2b..4a2523440f0f0 100644
--- a/llvm/lib/TargetParser/AArch64TargetParser.cpp
+++ b/llvm/lib/TargetParser/AArch64TargetParser.cpp
@@ -60,7 +60,7 @@ uint64_t AArch64::getFMVPriority(ArrayRef<StringRef> Features) {
ExtensionSet FeatureBits;
for (const StringRef Feature : Features) {
std::optional<FMVInfo> FMV = parseFMVExtension(Feature);
- if (!FMV) {
+ if (!FMV && Feature.starts_with('+')) {
if (std::optional<ExtensionInfo> Info = targetFeatureToExtension(Feature))
FMV = lookupFMVByID(Info->ID);
}
@@ -181,7 +181,8 @@ std::optional<AArch64::FMVInfo> AArch64::parseFMVExtension(StringRef FMVExt) {
std::optional<AArch64::ExtensionInfo>
AArch64::targetFeatureToExtension(StringRef TargetFeature) {
for (const auto &E : Extensions)
- if (TargetFeature == E.PosTargetFeature)
+ if (TargetFeature == E.PosTargetFeature ||
+ TargetFeature == E.NegTargetFeature)
return E;
return {};
}
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index f4c93334ac682..468ef57cb5b9b 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -1831,6 +1831,22 @@ TEST_P(AArch64ExtensionDependenciesBaseCPUTestFixture,
}
}
+TEST(TargetParserTest, testAArch64ReconstructFromParsedFeatures) {
+ AArch64::ExtensionSet Extensions;
+ std::vector<std::string> FeatureOptions = {
+ "-sve2", "-Baz", "+sve", "+FooBar", "+sve2", "+neon", "-sve",
+ };
+ std::vector<std::string> NonExtensions;
+ Extensions.reconstructFromParsedFeatures(FeatureOptions, NonExtensions);
+
+ std::vector<std::string> NonExtensionsExpected = {"-Baz", "+FooBar"};
+ ASSERT_THAT(NonExtensions, testing::ContainerEq(NonExtensionsExpected));
+ std::vector<StringRef> Features;
+ Extensions.toLLVMFeatureList(Features);
+ std::vector<StringRef> FeaturesExpected = {"+sve2", "+neon", "-sve"};
+ ASSERT_THAT(FeaturesExpected, testing::ContainerEq(FeaturesExpected));
+}
+
AArch64ExtensionDependenciesBaseArchTestParams
AArch64ExtensionDependenciesArchData[] = {
// Base architecture features
|
Cannot test with But I added a test based on the |
@@ -60,7 +60,7 @@ uint64_t AArch64::getFMVPriority(ArrayRef<StringRef> Features) { | |||
ExtensionSet FeatureBits; | |||
for (const StringRef Feature : Features) { | |||
std::optional<FMVInfo> FMV = parseFMVExtension(Feature); | |||
if (!FMV) { | |||
if (!FMV && Feature.starts_with('+')) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to have empty string? If not then Feature[0] == '+'
should also work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it's explicitly stated that empty strings are forbidden, so wouldn't like to just make assumptions also as I don't expect this function to performance critical...
ASSERT_THAT(NonExtensions, testing::ContainerEq(NonExtensionsExpected)); | ||
std::vector<StringRef> Features; | ||
Extensions.toLLVMFeatureList(Features); | ||
std::vector<StringRef> FeaturesExpected = {"+neon", "-sve", "+sve2"}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect the following:
Touched: sve2, sve, neon
Enabled: neon
If an extension is Touched but not Enabled it should be printed with a '-'. That said I don't understand why we expect +sve2 and not -sve2. I would expect -sve to transitively disable sve2 since it is dependant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This particular interface does not seem to resolve dependencies.
The point I was trying to make with the test was that having -sve2
followed by a +sve2
you end up with +sve2
. While having a +sve
followed by a -sve
will end up with -sve
etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we were trying to fix reconstructFromParsedFeatures so that it honors negative features. If you look at the code it does Enabled.reset
which should remove a feature and its dependencies.
If I am not mistaken at the point of calling reconstructFromParsedFeatures the command line arguments should already be processed having no contradictions like -featureA, +featureA (or reversed).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you look at the code it does Enabled.reset which should remove a feature and its dependencies.
Actually I was mistaken, Enabled.reset
should not transitively remove dependencies. Callingdisable()
would do that, but as I said this is probably redundant since the command line arguments have been processed at this stage.
This code inside reconstructFromParsedFeatures
seems dead
if (IsNegated)
Enabled.reset(AE->ID);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for adding the test. Unfortunately because it looks invalid to me, I still don't understand what the user facing problem is. Can you give a clang driver command line + C file that exhibits it?
// RUN: %clang_cc1 -triple aarch64-- -target-feature +neon -target-feature +sve\ | ||
// RUN: -target-feature -sve -emit-llvm %s -o - | FileCheck %s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The driver should never emit a -cc1
command line with -target-feature +sve -target-feature -sve
, so I don't think this is a valid way to test whatever the problem is.
// Reproducer for bug where clang would reject always_inline for unrelated | ||
// target features if they were disable with `-feature` on the command line. | ||
// CHECK: @bar | ||
__attribute__((always_inline)) __attribute__((target("neon"))) void foo() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
neon
is not actually a valid argument here, it should be simd
.
https://gcc.gnu.org/onlinedocs/gcc/AArch64-Options.html#index-march
|
||
// Reproducer for bug where clang would reject always_inline for unrelated | ||
// target features if they were disable with `-feature` on the command line. | ||
// CHECK: @bar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to check the LLVM IR attributes
for both functions, which is what reconstructFromParsedFeatures
is used to construct.
TEST(TargetParserTest, testAArch64ReconstructFromParsedFeatures) { | ||
AArch64::ExtensionSet Extensions; | ||
std::vector<std::string> FeatureOptions = { | ||
"-sve2", "-Baz", "+sve", "+FooBar", "+sve2", "+neon", "-sve", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this has the same issue as described for the C test: the function is not designed to be able to handle both +feat
and -feat
in the same list, because the driver would never emit that.
The
targetFeatureToExtension
function used byreconstructFromParsedFeatures only found positive
+FEATURE
strings,but not negative
-FEATURE
strings. Extend the function to handle bothto fix
reconstructFromParsedFeatures
.