mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-17 03:26:03 +00:00
Add an "implies" field to features. This indicates that, if the current
feature is set, then the features in the implied list should be set also. The opposite is also enforced: if a feature in the implied list isn't set, then the feature that owns that implies list shouldn't be set either. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36756 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2e7899dae9
commit
4222d806fa
@ -34,6 +34,7 @@ struct SubtargetFeatureKV {
|
|||||||
const char *Key; // K-V key string
|
const char *Key; // K-V key string
|
||||||
const char *Desc; // Help descriptor
|
const char *Desc; // Help descriptor
|
||||||
uint32_t Value; // K-V integer value
|
uint32_t Value; // K-V integer value
|
||||||
|
uint32_t Implies; // K-V bit mask
|
||||||
|
|
||||||
// Compare routine for std binary search
|
// Compare routine for std binary search
|
||||||
bool operator<(const SubtargetFeatureKV &S) const {
|
bool operator<(const SubtargetFeatureKV &S) const {
|
||||||
|
@ -199,6 +199,43 @@ void SubtargetFeatures::setCPUIfNone(const std::string &String) {
|
|||||||
if (Features[0].empty()) setCPU(String);
|
if (Features[0].empty()) setCPU(String);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SetImpliedBits - For each feature that is (transitively) implied by this
|
||||||
|
/// feature, set it.
|
||||||
|
///
|
||||||
|
static
|
||||||
|
void SetImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
|
||||||
|
const SubtargetFeatureKV *FeatureTable,
|
||||||
|
size_t FeatureTableSize) {
|
||||||
|
for (size_t i = 0; i < FeatureTableSize; ++i) {
|
||||||
|
const SubtargetFeatureKV &FE = FeatureTable[i];
|
||||||
|
|
||||||
|
if (FeatureEntry->Value == FE.Value) continue;
|
||||||
|
|
||||||
|
if (FeatureEntry->Implies & FE.Value) {
|
||||||
|
Bits |= FE.Value;
|
||||||
|
SetImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ClearImpliedBits - For each feature that (transitively) implies this
|
||||||
|
/// feature, clear it.
|
||||||
|
///
|
||||||
|
static
|
||||||
|
void ClearImpliedBits(uint32_t &Bits, const SubtargetFeatureKV *FeatureEntry,
|
||||||
|
const SubtargetFeatureKV *FeatureTable,
|
||||||
|
size_t FeatureTableSize) {
|
||||||
|
for (size_t i = 0; i < FeatureTableSize; ++i) {
|
||||||
|
const SubtargetFeatureKV &FE = FeatureTable[i];
|
||||||
|
|
||||||
|
if (FeatureEntry->Value == FE.Value) continue;
|
||||||
|
|
||||||
|
if (FE.Implies & FeatureEntry->Value) {
|
||||||
|
Bits &= ~FE.Value;
|
||||||
|
ClearImpliedBits(Bits, &FE, FeatureTable, FeatureTableSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// getBits - Get feature bits.
|
/// getBits - Get feature bits.
|
||||||
///
|
///
|
||||||
@ -251,8 +288,17 @@ uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable,
|
|||||||
// If there is a match
|
// If there is a match
|
||||||
if (FeatureEntry) {
|
if (FeatureEntry) {
|
||||||
// Enable/disable feature in bits
|
// Enable/disable feature in bits
|
||||||
if (isEnabled(Feature)) Bits |= FeatureEntry->Value;
|
if (isEnabled(Feature)) {
|
||||||
else Bits &= ~FeatureEntry->Value;
|
Bits |= FeatureEntry->Value;
|
||||||
|
|
||||||
|
// For each feature that this implies, set it.
|
||||||
|
SetImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
|
||||||
|
} else {
|
||||||
|
Bits &= ~FeatureEntry->Value;
|
||||||
|
|
||||||
|
// For each feature that implies this, clear it.
|
||||||
|
ClearImpliedBits(Bits, FeatureEntry, FeatureTable, FeatureTableSize);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cerr << "'" << Feature
|
cerr << "'" << Feature
|
||||||
<< "' is not a recognized feature for this target"
|
<< "' is not a recognized feature for this target"
|
||||||
@ -260,6 +306,7 @@ uint32_t SubtargetFeatures::getBits(const SubtargetFeatureKV *CPUTable,
|
|||||||
<< "\n";
|
<< "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Bits;
|
return Bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,7 +338,8 @@ class Target {
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// SubtargetFeature - A characteristic of the chip set.
|
// SubtargetFeature - A characteristic of the chip set.
|
||||||
//
|
//
|
||||||
class SubtargetFeature<string n, string a, string v, string d> {
|
class SubtargetFeature<string n, string a, string v, string d,
|
||||||
|
list<SubtargetFeature> i = []> {
|
||||||
// Name - Feature name. Used by command line (-mattr=) to determine the
|
// Name - Feature name. Used by command line (-mattr=) to determine the
|
||||||
// appropriate target chip.
|
// appropriate target chip.
|
||||||
//
|
//
|
||||||
@ -356,6 +357,11 @@ class SubtargetFeature<string n, string a, string v, string d> {
|
|||||||
// information.
|
// information.
|
||||||
//
|
//
|
||||||
string Desc = d;
|
string Desc = d;
|
||||||
|
|
||||||
|
// Implies - Features that this feature implies are present. If one of those
|
||||||
|
// features isn't set, then this one shouldn't be set either.
|
||||||
|
//
|
||||||
|
list<SubtargetFeature> Implies = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -18,24 +18,28 @@ include "../Target.td"
|
|||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// X86 Subtarget features.
|
// X86 Subtarget features.
|
||||||
//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true",
|
def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true",
|
||||||
"Support 64-bit instructions">;
|
"Support 64-bit instructions">;
|
||||||
def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX",
|
def FeatureMMX : SubtargetFeature<"mmx","X86SSELevel", "MMX",
|
||||||
"Enable MMX instructions">;
|
"Enable MMX instructions">;
|
||||||
def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1",
|
def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1",
|
||||||
"Enable SSE instructions">;
|
"Enable SSE instructions",
|
||||||
def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2",
|
[FeatureMMX]>;
|
||||||
"Enable SSE2 instructions">;
|
def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2",
|
||||||
def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3",
|
"Enable SSE2 instructions",
|
||||||
"Enable SSE3 instructions">;
|
[FeatureSSE1]>;
|
||||||
def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3",
|
def FeatureSSE3 : SubtargetFeature<"sse3", "X86SSELevel", "SSE3",
|
||||||
"Enable SSSE3 instructions">;
|
"Enable SSE3 instructions",
|
||||||
def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow",
|
[FeatureSSE2]>;
|
||||||
"Enable 3DNow! instructions">;
|
def FeatureSSSE3 : SubtargetFeature<"ssse3", "X86SSELevel", "SSSE3",
|
||||||
def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA",
|
"Enable SSSE3 instructions",
|
||||||
"Enable 3DNow! Athlon instructions">;
|
[FeatureSSE3]>;
|
||||||
|
def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow",
|
||||||
|
"Enable 3DNow! instructions">;
|
||||||
|
def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA",
|
||||||
|
"Enable 3DNow! Athlon instructions">;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// X86 processors supported.
|
// X86 processors supported.
|
||||||
|
@ -56,8 +56,7 @@ void SubtargetEmitter::Enumeration(std::ostream &OS,
|
|||||||
Record *Def = DefList[i];
|
Record *Def = DefList[i];
|
||||||
|
|
||||||
// Get and emit name
|
// Get and emit name
|
||||||
std::string Name = Def->getName();
|
OS << " " << Def->getName();
|
||||||
OS << " " << Name;
|
|
||||||
|
|
||||||
// If bit flags then emit expression (1 << i)
|
// If bit flags then emit expression (1 << i)
|
||||||
if (isBits) OS << " = " << " 1 << " << i;
|
if (isBits) OS << " = " << " 1 << " << i;
|
||||||
@ -73,8 +72,8 @@ void SubtargetEmitter::Enumeration(std::ostream &OS,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// FeatureKeyValues - Emit data of all the subtarget features. Used by command
|
// FeatureKeyValues - Emit data of all the subtarget features. Used by the
|
||||||
// line.
|
// command line.
|
||||||
//
|
//
|
||||||
void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
|
void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
|
||||||
// Gather and sort all the features
|
// Gather and sort all the features
|
||||||
@ -91,18 +90,31 @@ void SubtargetEmitter::FeatureKeyValues(std::ostream &OS) {
|
|||||||
// Next feature
|
// Next feature
|
||||||
Record *Feature = FeatureList[i];
|
Record *Feature = FeatureList[i];
|
||||||
|
|
||||||
std::string Name = Feature->getName();
|
const std::string &Name = Feature->getName();
|
||||||
std::string CommandLineName = Feature->getValueAsString("Name");
|
const std::string &CommandLineName = Feature->getValueAsString("Name");
|
||||||
std::string Desc = Feature->getValueAsString("Desc");
|
const std::string &Desc = Feature->getValueAsString("Desc");
|
||||||
|
|
||||||
if (CommandLineName.empty()) continue;
|
if (CommandLineName.empty()) continue;
|
||||||
|
|
||||||
// Emit as { "feature", "decription", feactureEnum }
|
// Emit as { "feature", "decription", feactureEnum, i1 | i2 | ... | in }
|
||||||
OS << " { "
|
OS << " { "
|
||||||
<< "\"" << CommandLineName << "\", "
|
<< "\"" << CommandLineName << "\", "
|
||||||
<< "\"" << Desc << "\", "
|
<< "\"" << Desc << "\", "
|
||||||
<< Name
|
<< Name << ", ";
|
||||||
<< " }";
|
|
||||||
|
const std::vector<Record*> &ImpliesList =
|
||||||
|
Feature->getValueAsListOfDefs("Implies");
|
||||||
|
|
||||||
|
if (ImpliesList.empty()) {
|
||||||
|
OS << "0";
|
||||||
|
} else {
|
||||||
|
for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
|
||||||
|
OS << ImpliesList[j]->getName();
|
||||||
|
if (++j < M) OS << " | ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OS << " }";
|
||||||
|
|
||||||
// Depending on 'if more in the list' emit comma
|
// Depending on 'if more in the list' emit comma
|
||||||
if ((i + 1) < N) OS << ",";
|
if ((i + 1) < N) OS << ",";
|
||||||
@ -138,8 +150,8 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) {
|
|||||||
// Next processor
|
// Next processor
|
||||||
Record *Processor = ProcessorList[i];
|
Record *Processor = ProcessorList[i];
|
||||||
|
|
||||||
std::string Name = Processor->getValueAsString("Name");
|
const std::string &Name = Processor->getValueAsString("Name");
|
||||||
std::vector<Record*> FeatureList =
|
const std::vector<Record*> &FeatureList =
|
||||||
Processor->getValueAsListOfDefs("Features");
|
Processor->getValueAsListOfDefs("Features");
|
||||||
|
|
||||||
// Emit as { "cpu", "description", f1 | f2 | ... fn },
|
// Emit as { "cpu", "description", f1 | f2 | ... fn },
|
||||||
@ -151,14 +163,13 @@ void SubtargetEmitter::CPUKeyValues(std::ostream &OS) {
|
|||||||
OS << "0";
|
OS << "0";
|
||||||
} else {
|
} else {
|
||||||
for (unsigned j = 0, M = FeatureList.size(); j < M;) {
|
for (unsigned j = 0, M = FeatureList.size(); j < M;) {
|
||||||
Record *Feature = FeatureList[j];
|
OS << FeatureList[j]->getName();
|
||||||
std::string Name = Feature->getName();
|
|
||||||
OS << Name;
|
|
||||||
if (++j < M) OS << " | ";
|
if (++j < M) OS << " | ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
OS << " }";
|
// The "0" is for the "implies" section of this data structure.
|
||||||
|
OS << ", 0 }";
|
||||||
|
|
||||||
// Depending on 'if more in the list' emit comma
|
// Depending on 'if more in the list' emit comma
|
||||||
if (++i < N) OS << ",";
|
if (++i < N) OS << ",";
|
||||||
@ -190,11 +201,10 @@ unsigned SubtargetEmitter::CollectAllItinClasses(std::ostream &OS,
|
|||||||
unsigned N = ItinClassList.size();
|
unsigned N = ItinClassList.size();
|
||||||
for (unsigned i = 0; i < N; i++) {
|
for (unsigned i = 0; i < N; i++) {
|
||||||
// Next itinerary class
|
// Next itinerary class
|
||||||
Record *ItinClass = ItinClassList[i];
|
const Record *ItinClass = ItinClassList[i];
|
||||||
// Get name of itinerary class
|
// Get name of itinerary class
|
||||||
std::string Name = ItinClass->getName();
|
|
||||||
// Assign itinerary class a unique number
|
// Assign itinerary class a unique number
|
||||||
ItinClassesMap[Name] = i;
|
ItinClassesMap[ItinClass->getName()] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit size of table
|
// Emit size of table
|
||||||
@ -214,28 +224,26 @@ void SubtargetEmitter::FormItineraryString(Record *ItinData,
|
|||||||
std::string &ItinString,
|
std::string &ItinString,
|
||||||
unsigned &NStages) {
|
unsigned &NStages) {
|
||||||
// Get states list
|
// Get states list
|
||||||
std::vector<Record*> StageList = ItinData->getValueAsListOfDefs("Stages");
|
const std::vector<Record*> &StageList =
|
||||||
|
ItinData->getValueAsListOfDefs("Stages");
|
||||||
|
|
||||||
// For each stage
|
// For each stage
|
||||||
unsigned N = NStages = StageList.size();
|
unsigned N = NStages = StageList.size();
|
||||||
for (unsigned i = 0; i < N;) {
|
for (unsigned i = 0; i < N;) {
|
||||||
// Next stage
|
// Next stage
|
||||||
Record *Stage = StageList[i];
|
const Record *Stage = StageList[i];
|
||||||
|
|
||||||
// Form string as ,{ cycles, u1 | u2 | ... | un }
|
// Form string as ,{ cycles, u1 | u2 | ... | un }
|
||||||
int Cycles = Stage->getValueAsInt("Cycles");
|
int Cycles = Stage->getValueAsInt("Cycles");
|
||||||
ItinString += " { " + itostr(Cycles) + ", ";
|
ItinString += " { " + itostr(Cycles) + ", ";
|
||||||
|
|
||||||
// Get unit list
|
// Get unit list
|
||||||
std::vector<Record*> UnitList = Stage->getValueAsListOfDefs("Units");
|
const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
|
||||||
|
|
||||||
// For each unit
|
// For each unit
|
||||||
for (unsigned j = 0, M = UnitList.size(); j < M;) {
|
for (unsigned j = 0, M = UnitList.size(); j < M;) {
|
||||||
// Next unit
|
|
||||||
Record *Unit = UnitList[j];
|
|
||||||
|
|
||||||
// Add name and bitwise or
|
// Add name and bitwise or
|
||||||
ItinString += Unit->getName();
|
ItinString += UnitList[j]->getName();
|
||||||
if (++j < M) ItinString += " | ";
|
if (++j < M) ItinString += " | ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,7 +279,7 @@ void SubtargetEmitter::EmitStageData(std::ostream &OS,
|
|||||||
Record *Proc = ProcItinList[i];
|
Record *Proc = ProcItinList[i];
|
||||||
|
|
||||||
// Get processor itinerary name
|
// Get processor itinerary name
|
||||||
std::string Name = Proc->getName();
|
const std::string &Name = Proc->getName();
|
||||||
|
|
||||||
// Skip default
|
// Skip default
|
||||||
if (Name == "NoItineraries") continue;
|
if (Name == "NoItineraries") continue;
|
||||||
@ -308,7 +316,7 @@ void SubtargetEmitter::EmitStageData(std::ostream &OS,
|
|||||||
InstrItinerary Intinerary = { Find, Find + NStages };
|
InstrItinerary Intinerary = { Find, Find + NStages };
|
||||||
|
|
||||||
// Locate where to inject into processor itinerary table
|
// Locate where to inject into processor itinerary table
|
||||||
std::string Name = ItinData->getValueAsDef("TheClass")->getName();
|
const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
|
||||||
Find = ItinClassesMap[Name];
|
Find = ItinClassesMap[Name];
|
||||||
|
|
||||||
// Inject - empty slots will be 0, 0
|
// Inject - empty slots will be 0, 0
|
||||||
@ -347,7 +355,7 @@ void SubtargetEmitter::EmitProcessorData(std::ostream &OS,
|
|||||||
Record *Itin = Itins[i];
|
Record *Itin = Itins[i];
|
||||||
|
|
||||||
// Get processor itinerary name
|
// Get processor itinerary name
|
||||||
std::string Name = Itin->getName();
|
const std::string &Name = Itin->getName();
|
||||||
|
|
||||||
// Skip default
|
// Skip default
|
||||||
if (Name == "NoItineraries") continue;
|
if (Name == "NoItineraries") continue;
|
||||||
@ -398,8 +406,9 @@ void SubtargetEmitter::EmitProcessorLookup(std::ostream &OS) {
|
|||||||
// Next processor
|
// Next processor
|
||||||
Record *Processor = ProcessorList[i];
|
Record *Processor = ProcessorList[i];
|
||||||
|
|
||||||
std::string Name = Processor->getValueAsString("Name");
|
const std::string &Name = Processor->getValueAsString("Name");
|
||||||
std::string ProcItin = Processor->getValueAsDef("ProcItin")->getName();
|
const std::string &ProcItin =
|
||||||
|
Processor->getValueAsDef("ProcItin")->getName();
|
||||||
|
|
||||||
// Emit as { "cpu", procinit },
|
// Emit as { "cpu", procinit },
|
||||||
OS << " { "
|
OS << " { "
|
||||||
@ -456,23 +465,22 @@ void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) {
|
|||||||
std::sort(Features.begin(), Features.end(), LessRecord());
|
std::sort(Features.begin(), Features.end(), LessRecord());
|
||||||
|
|
||||||
OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
|
OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
|
||||||
"// subtarget options.\n"
|
<< "// subtarget options.\n"
|
||||||
"void llvm::";
|
<< "void llvm::";
|
||||||
OS << Target;
|
OS << Target;
|
||||||
OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
|
OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
|
||||||
" const std::string &CPU) {\n"
|
<< " const std::string &CPU) {\n"
|
||||||
" SubtargetFeatures Features(FS);\n"
|
<< " SubtargetFeatures Features(FS);\n"
|
||||||
" Features.setCPUIfNone(CPU);\n"
|
<< " Features.setCPUIfNone(CPU);\n"
|
||||||
" uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n"
|
<< " uint32_t Bits = Features.getBits(SubTypeKV, SubTypeKVSize,\n"
|
||||||
" FeatureKV, FeatureKVSize);\n";
|
<< " FeatureKV, FeatureKVSize);\n";
|
||||||
|
|
||||||
for (unsigned i = 0; i < Features.size(); i++) {
|
for (unsigned i = 0; i < Features.size(); i++) {
|
||||||
// Next record
|
// Next record
|
||||||
Record *R = Features[i];
|
Record *R = Features[i];
|
||||||
std::string Instance = R->getName();
|
const std::string &Instance = R->getName();
|
||||||
std::string Name = R->getValueAsString("Name");
|
const std::string &Value = R->getValueAsString("Value");
|
||||||
std::string Value = R->getValueAsString("Value");
|
const std::string &Attribute = R->getValueAsString("Attribute");
|
||||||
std::string Attribute = R->getValueAsString("Attribute");
|
|
||||||
|
|
||||||
OS << " if ((Bits & " << Instance << ") != 0) "
|
OS << " if ((Bits & " << Instance << ") != 0) "
|
||||||
<< Attribute << " = " << Value << ";\n";
|
<< Attribute << " = " << Value << ";\n";
|
||||||
@ -481,8 +489,8 @@ void SubtargetEmitter::ParseFeaturesFunction(std::ostream &OS) {
|
|||||||
if (HasItineraries) {
|
if (HasItineraries) {
|
||||||
OS << "\n"
|
OS << "\n"
|
||||||
<< " InstrItinerary *Itinerary = (InstrItinerary *)"
|
<< " InstrItinerary *Itinerary = (InstrItinerary *)"
|
||||||
"Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
|
<< "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
|
||||||
" InstrItins = InstrItineraryData(Stages, Itinerary);\n";
|
<< " InstrItins = InstrItineraryData(Stages, Itinerary);\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
OS << "}\n";
|
OS << "}\n";
|
||||||
|
Loading…
Reference in New Issue
Block a user