diff --git a/llvm/lib/MC/MCSubtargetInfo.cpp b/llvm/lib/MC/MCSubtargetInfo.cpp --- a/llvm/lib/MC/MCSubtargetInfo.cpp +++ b/llvm/lib/MC/MCSubtargetInfo.cpp @@ -56,7 +56,7 @@ } } -static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, +static bool ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, ArrayRef FeatureTable) { assert(SubtargetFeatures::hasFlag(Feature) && "Feature flags should start with '+' or '-'"); @@ -78,10 +78,13 @@ // For each feature that implies this, clear it. ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable); } + return true; } else { errs() << "'" << Feature << "' is not a recognized feature for this target" << " (ignoring feature)\n"; + return false; } + return false; } /// Return the length of the longest entry in the table. @@ -297,13 +300,19 @@ bool MCSubtargetInfo::checkFeatures(StringRef FS) const { SubtargetFeatures T(FS); - FeatureBitset Set, All; + FeatureBitset Set, All, Empty; for (std::string F : T.getFeatures()) { - ::ApplyFeatureFlag(Set, F, ProcFeatures); + if (!::ApplyFeatureFlag(Set, F, ProcFeatures)) + continue; if (F[0] == '-') F[0] = '+'; - ::ApplyFeatureFlag(All, F, ProcFeatures); + (void)::ApplyFeatureFlag(All, F, ProcFeatures); } + + // All input features are unknown features. + if (Set == Empty && All == Empty) + return false; + return (FeatureBits & All) == Set; } diff --git a/llvm/unittests/CodeGen/TargetOptionsTest.cpp b/llvm/unittests/CodeGen/TargetOptionsTest.cpp --- a/llvm/unittests/CodeGen/TargetOptionsTest.cpp +++ b/llvm/unittests/CodeGen/TargetOptionsTest.cpp @@ -3,6 +3,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/InitializePasses.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Target/TargetMachine.h" @@ -39,8 +40,8 @@ TargetOptions Options; Options.EnableIPRA = EnableIPRA; return std::unique_ptr( - T->createTargetMachine("X86", "", "", Options, std::nullopt, std::nullopt, - CodeGenOpt::Aggressive)); + T->createTargetMachine("X86", "", "+avx", Options, std::nullopt, + std::nullopt, CodeGenOpt::Aggressive)); } typedef std::function TargetOptionsTest; @@ -61,6 +62,17 @@ delete TPC; } +static void targetFeaturesTest(StringRef F) { + std::unique_ptr TM = createTargetMachine(false); + // This test is designed for the X86 backend; stop if it is not available. + if (!TM) + GTEST_SKIP(); + + ASSERT_NE(TM->getMCSubtargetInfo(), nullptr); + + ASSERT_FALSE(TM->getMCSubtargetInfo()->checkFeatures(F)); +} + } // End of anonymous namespace. TEST(TargetOptionsTest, IPRASetToOff) { @@ -71,6 +83,10 @@ targetOptionsTest(true); } +TEST(TargetOptionsTest, KnownFeature) { targetFeaturesTest("-avx"); } + +TEST(TargetOptionsTest, UnknownFeature) { targetFeaturesTest("+relax"); } + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); initLLVM();