diff --git a/llvm/test/TableGen/DuplicateProcessorFeatures.td b/llvm/test/TableGen/DuplicateProcessorFeatures.td new file mode 100644 index 0000000000000..45df2d814bcbd --- /dev/null +++ b/llvm/test/TableGen/DuplicateProcessorFeatures.td @@ -0,0 +1,17 @@ +// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s 2>&1 | FileCheck %s + +include "llvm/Target/Target.td" + +def MyTarget : Target; + +def FeatureA : SubtargetFeature<"NameA", "", "", "">; +def FeatureB : SubtargetFeature<"NameB", "", "", "">; +def FeatureC : SubtargetFeature<"NameC", "", "", "">; + +// CHECK: warning: Processor CPU0 contains duplicate feature 'NameA' +def P0 : ProcessorModel<"CPU0", NoSchedModel, [FeatureA, FeatureB, FeatureA]>; +// CHECK: warning: Processor CPU1 contains duplicate tune feature 'NameB' +// CHECK: warning: Processor CPU1 has 'NameC' in both feature and tune feature sets +def P1 : ProcessorModel<"CPU1", NoSchedModel, + /*Features=*/[FeatureC], + /*TuneFeatures=*/[FeatureB, FeatureB, FeatureC]>; diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp index 8d2fc99f84670..96cbfba9bd27f 100644 --- a/llvm/utils/TableGen/SubtargetEmitter.cpp +++ b/llvm/utils/TableGen/SubtargetEmitter.cpp @@ -333,6 +333,30 @@ unsigned SubtargetEmitter::cpuNames(raw_ostream &OS) { return Names.size(); } +static void checkDuplicateCPUFeatures(StringRef CPUName, + ArrayRef Features, + ArrayRef TuneFeatures) { + // We have made sure each SubtargetFeature Record has a unique name, so we can + // simply use pointer sets here. + SmallPtrSet FeatureSet, TuneFeatureSet; + for (const auto *FeatureRec : Features) { + if (!FeatureSet.insert(FeatureRec).second) + PrintWarning("Processor " + CPUName + " contains duplicate feature '" + + FeatureRec->getValueAsString("Name") + "'"); + } + + for (const auto *TuneFeatureRec : TuneFeatures) { + if (!TuneFeatureSet.insert(TuneFeatureRec).second) + PrintWarning("Processor " + CPUName + + " contains duplicate tune feature '" + + TuneFeatureRec->getValueAsString("Name") + "'"); + if (FeatureSet.contains(TuneFeatureRec)) + PrintWarning("Processor " + CPUName + " has '" + + TuneFeatureRec->getValueAsString("Name") + + "' in both feature and tune feature sets"); + } +} + // // CPUKeyValues - Emit data of all the subtarget processors. Used by command // line. @@ -360,6 +384,10 @@ unsigned SubtargetEmitter::cpuKeyValues(raw_ostream &OS, ConstRecVec TuneFeatureList = Processor->getValueAsListOfDefs("TuneFeatures"); + // Warn the user if there are duplicate processor features or tune + // features. + checkDuplicateCPUFeatures(Name, FeatureList, TuneFeatureList); + // Emit as "{ "cpu", "description", 0, { f1 , f2 , ... fn } },". OS << " { " << "\"" << Name << "\", ";