aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2012-08-17 14:35:45 -0700
committerDerek Schuff <dschuff@chromium.org>2012-08-17 14:35:45 -0700
commitb62e9abf7dd9e39c95327914ce9dfe216386824a (patch)
treec683f0bcbef19f622727251165eaf89a4f806c62 /utils/TableGen
parent66f65db9406ca9e59d4bfed89436f668d6a84374 (diff)
parentc723eb1aef817d47feec620933ee1ec6005cdd14 (diff)
Merge commit 'c723eb1aef817d47feec620933ee1ec6005cdd14'
This merges r159618 from upstream into master. It goes with clang rev af50aab0c317462129d73ae8000c6394c718598d Conflicts: include/llvm/CodeGen/LexicalScopes.h include/llvm/Target/TargetOptions.h lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp lib/Target/ARM/ARMBaseInstrInfo.cpp lib/Target/ARM/ARMTargetMachine.cpp lib/Target/ARM/ARMTargetObjectFile.cpp lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp lib/Target/Mips/MipsISelDAGToDAG.cpp lib/Target/Mips/MipsInstrFPU.td lib/Target/Mips/MipsMCInstLower.cpp lib/Target/Mips/MipsTargetMachine.cpp lib/Target/TargetMachine.cpp lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86RegisterInfo.cpp lib/Target/X86/X86TargetObjectFile.cpp lib/Target/X86/X86TargetObjectFile.h tools/llc/llc.cpp (tools/llc/llc.cpp is from a merged version of r160532 because it was a bit hairy and I didn't want to redo it.)
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp99
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp7
-rw-r--r--utils/TableGen/DFAPacketizerEmitter.cpp70
-rw-r--r--utils/TableGen/EDEmitter.cpp2
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp80
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp4
6 files changed, 184 insertions, 78 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index e980b1a7d9..f5e094e486 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -186,6 +186,8 @@ struct ClassInfo {
/// For register classes, the records for all the registers in this class.
std::set<Record*> Registers;
+ /// For custom match classes, he diagnostic kind for when the predicate fails.
+ std::string DiagnosticType;
public:
/// isRegisterClass() - Check if this is a register class.
bool isRegisterClass() const {
@@ -593,6 +595,9 @@ public:
/// Map of Predicate records to their subtarget information.
std::map<Record*, SubtargetFeatureInfo*> SubtargetFeatures;
+ /// Map of AsmOperandClass records to their class information.
+ std::map<Record*, ClassInfo*> AsmOperandClasses;
+
private:
/// Map of token to class information which has already been constructed.
std::map<std::string, ClassInfo*> TokenClasses;
@@ -600,9 +605,6 @@ private:
/// Map of RegisterClass records to their class information.
std::map<Record*, ClassInfo*> RegisterClassClasses;
- /// Map of AsmOperandClass records to their class information.
- std::map<Record*, ClassInfo*> AsmOperandClasses;
-
private:
/// getTokenClass - Lookup or create the class for the given token.
ClassInfo *getTokenClass(StringRef Token);
@@ -960,6 +962,7 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
Entry->PredicateMethod = "<invalid>";
Entry->RenderMethod = "<invalid>";
Entry->ParserMethod = "";
+ Entry->DiagnosticType = "";
Classes.push_back(Entry);
}
@@ -1085,6 +1088,8 @@ buildRegisterClasses(SmallPtrSet<Record*, 16> &SingletonRegisters) {
CI->PredicateMethod = ""; // unused
CI->RenderMethod = "addRegOperands";
CI->Registers = *it;
+ // FIXME: diagnostic type.
+ CI->DiagnosticType = "";
Classes.push_back(CI);
RegisterSetClasses.insert(std::make_pair(*it, CI));
}
@@ -1200,6 +1205,12 @@ void AsmMatcherInfo::buildOperandClasses() {
if (StringInit *SI = dynamic_cast<StringInit*>(PRMName))
CI->ParserMethod = SI->getValue();
+ // Get the diagnostic type or leave it as empty.
+ // Get the parse method name or leave it as empty.
+ Init *DiagnosticType = (*it)->getValueInit("DiagnosticType");
+ if (StringInit *SI = dynamic_cast<StringInit*>(DiagnosticType))
+ CI->DiagnosticType = SI->getValue();
+
AsmOperandClasses[*it] = CI;
Classes.push_back(CI);
}
@@ -1802,19 +1813,21 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target,
/// emitValidateOperandClass - Emit the function to validate an operand class.
static void emitValidateOperandClass(AsmMatcherInfo &Info,
raw_ostream &OS) {
- OS << "static bool validateOperandClass(MCParsedAsmOperand *GOp, "
+ OS << "static unsigned validateOperandClass(MCParsedAsmOperand *GOp, "
<< "MatchClassKind Kind) {\n";
OS << " " << Info.Target.getName() << "Operand &Operand = *("
<< Info.Target.getName() << "Operand*)GOp;\n";
// The InvalidMatchClass is not to match any operand.
OS << " if (Kind == InvalidMatchClass)\n";
- OS << " return false;\n\n";
+ OS << " return MCTargetAsmParser::Match_InvalidOperand;\n\n";
// Check for Token operands first.
+ // FIXME: Use a more specific diagnostic type.
OS << " if (Operand.isToken())\n";
- OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind);"
- << "\n\n";
+ OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind) ?\n"
+ << " MCTargetAsmParser::Match_Success :\n"
+ << " MCTargetAsmParser::Match_InvalidOperand;\n\n";
// Check for register operands, including sub-classes.
OS << " if (Operand.isReg()) {\n";
@@ -1828,8 +1841,9 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
<< it->first->getName() << ": OpKind = " << it->second->Name
<< "; break;\n";
OS << " }\n";
- OS << " return isSubclass(OpKind, Kind);\n";
- OS << " }\n\n";
+ OS << " return isSubclass(OpKind, Kind) ? "
+ << "MCTargetAsmParser::Match_Success :\n "
+ << " MCTargetAsmParser::Match_InvalidOperand;\n }\n\n";
// Check the user classes. We don't care what order since we're only
// actually matching against one of them.
@@ -1841,13 +1855,18 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
continue;
OS << " // '" << CI.ClassName << "' class\n";
- OS << " if (Kind == " << CI.Name
- << " && Operand." << CI.PredicateMethod << "()) {\n";
- OS << " return true;\n";
+ OS << " if (Kind == " << CI.Name << ") {\n";
+ OS << " if (Operand." << CI.PredicateMethod << "())\n";
+ OS << " return MCTargetAsmParser::Match_Success;\n";
+ if (!CI.DiagnosticType.empty())
+ OS << " return " << Info.Target.getName() << "AsmParser::Match_"
+ << CI.DiagnosticType << ";\n";
OS << " }\n\n";
}
- OS << " return false;\n";
+ // Generic fallthrough match failure case for operands that don't have
+ // specialized diagnostic types.
+ OS << " return MCTargetAsmParser::Match_InvalidOperand;\n";
OS << "}\n\n";
}
@@ -1963,6 +1982,26 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info,
OS << "};\n\n";
}
+/// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types.
+static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) {
+ // Get the set of diagnostic types from all of the operand classes.
+ std::set<StringRef> Types;
+ for (std::map<Record*, ClassInfo*>::const_iterator
+ I = Info.AsmOperandClasses.begin(),
+ E = Info.AsmOperandClasses.end(); I != E; ++I) {
+ if (!I->second->DiagnosticType.empty())
+ Types.insert(I->second->DiagnosticType);
+ }
+
+ if (Types.empty()) return;
+
+ // Now emit the enum entries.
+ for (std::set<StringRef>::const_iterator I = Types.begin(), E = Types.end();
+ I != E; ++I)
+ OS << " Match_" << *I << ",\n";
+ OS << " END_OPERAND_DIAGNOSTIC_TYPES\n";
+}
+
/// emitGetSubtargetFeatureName - Emit the helper function to get the
/// user-level name for a subtarget feature.
static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
@@ -2394,6 +2433,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << "#endif // GET_ASSEMBLER_HEADER_INFO\n\n";
+ // Emit the operand match diagnostic enum names.
+ OS << "\n#ifdef GET_OPERAND_DIAGNOSTIC_TYPES\n";
+ OS << "#undef GET_OPERAND_DIAGNOSTIC_TYPES\n\n";
+ emitOperandDiagnosticTypes(Info, OS);
+ OS << "#endif // GET_OPERAND_DIAGNOSTIC_TYPES\n\n";
+
+
OS << "\n#ifdef GET_REGISTER_MATCHER\n";
OS << "#undef GET_REGISTER_MATCHER\n\n";
@@ -2575,6 +2621,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " bool HadMatchOtherThanFeatures = false;\n";
OS << " bool HadMatchOtherThanPredicate = false;\n";
OS << " unsigned RetCode = Match_InvalidOperand;\n";
+ OS << " unsigned MissingFeatures = ~0U;\n";
OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
OS << " // wrong for all instances of the instruction.\n";
OS << " ErrorInfo = ~0U;\n";
@@ -2604,13 +2651,22 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " OperandsValid = (it->Classes[i] == " <<"InvalidMatchClass);\n";
OS << " break;\n";
OS << " }\n";
- OS << " if (validateOperandClass(Operands[i+1], "
- "(MatchClassKind)it->Classes[i]))\n";
+ OS << " unsigned Diag = validateOperandClass(Operands[i+1],\n";
+ OS.indent(43);
+ OS << "(MatchClassKind)it->Classes[i]);\n";
+ OS << " if (Diag == Match_Success)\n";
OS << " continue;\n";
OS << " // If this operand is broken for all of the instances of this\n";
OS << " // mnemonic, keep track of it so we can report loc info.\n";
- OS << " if (it == MnemonicRange.first || ErrorInfo <= i+1)\n";
+ OS << " // If we already had a match that only failed due to a\n";
+ OS << " // target predicate, that diagnostic is preferred.\n";
+ OS << " if (!HadMatchOtherThanPredicate &&\n";
+ OS << " (it == MnemonicRange.first || ErrorInfo <= i+1)) {\n";
OS << " ErrorInfo = i+1;\n";
+ OS << " // InvalidOperand is the default. Prefer specificity.\n";
+ OS << " if (Diag != Match_InvalidOperand)\n";
+ OS << " RetCode = Diag;\n";
+ OS << " }\n";
OS << " // Otherwise, just reject this instance of the mnemonic.\n";
OS << " OperandsValid = false;\n";
OS << " break;\n";
@@ -2622,7 +2678,11 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " if ((AvailableFeatures & it->RequiredFeatures) "
<< "!= it->RequiredFeatures) {\n";
OS << " HadMatchOtherThanFeatures = true;\n";
- OS << " ErrorInfo = it->RequiredFeatures & ~AvailableFeatures;\n";
+ OS << " unsigned NewMissingFeatures = it->RequiredFeatures & "
+ "~AvailableFeatures;\n";
+ OS << " if (CountPopulation_32(NewMissingFeatures) <= "
+ "CountPopulation_32(MissingFeatures))\n";
+ OS << " MissingFeatures = NewMissingFeatures;\n";
OS << " continue;\n";
OS << " }\n";
OS << "\n";
@@ -2656,8 +2716,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " // Okay, we had no match. Try to return a useful error code.\n";
OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)";
- OS << " return RetCode;\n";
- OS << " assert(ErrorInfo && \"missing feature(s) but what?!\");";
+ OS << " return RetCode;\n";
+ OS << " // Missing feature matches return which features were missing\n";
+ OS << " ErrorInfo = MissingFeatures;\n";
OS << " return Match_MissingFeature;\n";
OS << "}\n\n";
diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 2ac7b87e70..aed222c094 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/utils/TableGen/DAGISelMatcherGen.cpp
@@ -690,6 +690,13 @@ EmitResultInstructionAsOperand(const TreePatternNode *N,
bool NodeHasChain = InstPatNode &&
InstPatNode->TreeHasProperty(SDNPHasChain, CGP);
+ // Instructions which load and store from memory should have a chain,
+ // regardless of whether they happen to have an internal pattern saying so.
+ if (Pattern.getSrcPattern()->TreeHasProperty(SDNPHasChain, CGP)
+ && (II.hasCtrlDep || II.mayLoad || II.mayStore || II.canFoldAsLoad ||
+ II.hasSideEffects))
+ NodeHasChain = true;
+
bool isRoot = N == Pattern.getDstPattern();
// TreeHasOutGlue - True if this tree has glue.
diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp
index 26ab76390e..8bfecead6d 100644
--- a/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -94,7 +94,12 @@ class State {
// PossibleStates is the set of valid resource states that ensue from valid
// transitions.
//
- bool canAddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates);
+ bool canAddInsnClass(unsigned InsnClass) const;
+ //
+ // AddInsnClass - Return all combinations of resource reservation
+ // which are possible from this state (PossibleStates).
+ //
+ void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates);
};
} // End anonymous namespace.
@@ -120,6 +125,10 @@ namespace {
struct ltState {
bool operator()(const State *s1, const State *s2) const;
};
+
+struct ltTransition {
+ bool operator()(const Transition *s1, const Transition *s2) const;
+};
} // End anonymous namespace.
@@ -135,7 +144,8 @@ public:
std::set<State*, ltState> states;
// Map from a state to the list of transitions with that state as source.
- std::map<State*, SmallVector<Transition*, 16>, ltState> stateTransitions;
+ std::map<State*, std::set<Transition*, ltTransition>, ltState>
+ stateTransitions;
State *currentState;
// Highest valued Input seen.
@@ -193,21 +203,19 @@ bool ltState::operator()(const State *s1, const State *s2) const {
return (s1->stateNum < s2->stateNum);
}
+bool ltTransition::operator()(const Transition *s1, const Transition *s2) const {
+ return (s1->input < s2->input);
+}
//
-// canAddInsnClass - Returns true if an instruction of type InsnClass is a
-// valid transition from this state i.e., can an instruction of type InsnClass
-// be added to the packet represented by this state.
+// AddInsnClass - Return all combinations of resource reservation
+// which are possible from this state (PossibleStates).
//
-// PossibleStates is the set of valid resource states that ensue from valid
-// transitions.
-//
-bool State::canAddInsnClass(unsigned InsnClass,
+void State::AddInsnClass(unsigned InsnClass,
std::set<unsigned> &PossibleStates) {
//
// Iterate over all resource states in currentState.
//
- bool AddedState = false;
for (std::set<unsigned>::iterator SI = stateInfo.begin();
SI != stateInfo.end(); ++SI) {
@@ -240,13 +248,26 @@ bool State::canAddInsnClass(unsigned InsnClass,
(VisitedResourceStates.count(ResultingResourceState) == 0)) {
VisitedResourceStates.insert(ResultingResourceState);
PossibleStates.insert(ResultingResourceState);
- AddedState = true;
}
}
}
}
- return AddedState;
+}
+
+
+//
+// canAddInsnClass - Quickly verifies if an instruction of type InsnClass is a
+// valid transition from this state i.e., can an instruction of type InsnClass
+// be added to the packet represented by this state.
+//
+bool State::canAddInsnClass(unsigned InsnClass) const {
+ for (std::set<unsigned>::const_iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI) {
+ if (~*SI & InsnClass)
+ return true;
+ }
+ return false;
}
@@ -267,7 +288,9 @@ void DFA::addTransition(Transition *T) {
LargestInput = T->input;
// Add the new transition.
- stateTransitions[T->from].push_back(T);
+ bool Added = stateTransitions[T->from].insert(T).second;
+ assert(Added && "Cannot have multiple states for the same input");
+ (void)Added;
}
@@ -281,11 +304,13 @@ State *DFA::getTransition(State *From, unsigned I) {
return NULL;
// Do we have a transition from state From with Input I?
- for (SmallVector<Transition*, 16>::iterator VI =
- stateTransitions[From].begin();
- VI != stateTransitions[From].end(); ++VI)
- if ((*VI)->input == I)
- return (*VI)->to;
+ Transition TVal(NULL, I, NULL);
+ // Do not count this temporal instance
+ Transition::currentTransitionNum--;
+ std::set<Transition*, ltTransition>::iterator T =
+ stateTransitions[From].find(&TVal);
+ if (T != stateTransitions[From].end())
+ return (*T)->to;
return NULL;
}
@@ -331,11 +356,12 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) {
StateEntry[i] = ValidTransitions;
for (unsigned j = 0; j <= LargestInput; ++j) {
assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers");
- if (!isValidTransition(*SI, j))
+ State *To = getTransition(*SI, j);
+ if (To == NULL)
continue;
OS << "{" << j << ", "
- << getTransition(*SI, j)->stateNum
+ << To->stateNum
<< "}, ";
++ValidTransitions;
}
@@ -514,8 +540,10 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
// and the state can accommodate this InsnClass, create a transition.
//
if (!D.getTransition(current, InsnClass) &&
- current->canAddInsnClass(InsnClass, NewStateResources)) {
+ current->canAddInsnClass(InsnClass)) {
State *NewState = NULL;
+ current->AddInsnClass(InsnClass, NewStateResources);
+ assert(NewStateResources.size() && "New states must be generated");
//
// If we have seen this state before, then do not create a new state.
diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp
index 6fb2feecbc..7b9354c169 100644
--- a/utils/TableGen/EDEmitter.cpp
+++ b/utils/TableGen/EDEmitter.cpp
@@ -317,6 +317,8 @@ static int X86TypeFromOpName(LiteralConstantEmitter *type,
MEM("i256mem");
MEM("f128mem");
MEM("f256mem");
+ MEM("v128mem");
+ MEM("v256mem");
MEM("opaque512mem");
// all R, I, R, I
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index 1b871a8b66..8089908c1f 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/utils/TableGen/SubtargetEmitter.cpp
@@ -422,15 +422,18 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
// Get processor itinerary name
const std::string &Name = Proc->getName();
- // Skip default
- if (Name == "NoItineraries") continue;
-
- // Create and expand processor itinerary to cover all itinerary classes
- std::vector<InstrItinerary> ItinList;
- ItinList.resize(NItinClasses);
-
// Get itinerary data list
std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
+ std::vector<InstrItinerary> ItinList;
+
+ // Add an empty itinerary.
+ if (ItinDataList.empty()) {
+ ProcList.push_back(ItinList);
+ continue;
+ }
+
+ // Expand processor itinerary to cover all itinerary classes
+ ItinList.resize(NItinClasses);
// For each itinerary data
for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {
@@ -495,7 +498,7 @@ void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
unsigned Find = ItinClassesMap[Name];
// Set up itinerary as location and location + stage count
- unsigned NumUOps = ItinClassList[Find]->getValueAsInt("NumMicroOps");
+ int NumUOps = ItinData->getValueAsInt("NumMicroOps");
InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
FindOperandCycle,
FindOperandCycle + NOperandCycles};
@@ -559,8 +562,6 @@ EmitProcessorData(raw_ostream &OS,
const std::string &Name = Itin->getName();
// Skip default
- if (Name == "NoItineraries") continue;
-
// Begin processor itinerary properties
OS << "\n";
OS << "static const llvm::InstrItineraryProps " << Name << "Props(\n";
@@ -570,42 +571,45 @@ EmitProcessorData(raw_ostream &OS,
EmitItineraryProp(OS, Itin, "HighLatency", ' ');
OS << ");\n";
- // Begin processor itinerary table
- OS << "\n";
- OS << "static const llvm::InstrItinerary " << Name << "Entries"
- << "[] = {\n";
-
// For each itinerary class
std::vector<InstrItinerary> &ItinList = *ProcListIter++;
- assert(ItinList.size() == ItinClassList.size() && "bad itinerary");
- for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
- InstrItinerary &Intinerary = ItinList[j];
-
- // Emit in the form of
- // { firstStage, lastStage, firstCycle, lastCycle } // index
- if (Intinerary.FirstStage == 0) {
- OS << " { 1, 0, 0, 0, 0 }";
- } else {
- OS << " { " <<
- Intinerary.NumMicroOps << ", " <<
- Intinerary.FirstStage << ", " <<
- Intinerary.LastStage << ", " <<
- Intinerary.FirstOperandCycle << ", " <<
- Intinerary.LastOperandCycle << " }";
- }
+ if (!ItinList.empty()) {
+ assert(ItinList.size() == ItinClassList.size() && "bad itinerary");
- OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n";
+ // Begin processor itinerary table
+ OS << "\n";
+ OS << "static const llvm::InstrItinerary " << Name << "Entries"
+ << "[] = {\n";
+
+ for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
+ InstrItinerary &Intinerary = ItinList[j];
+
+ // Emit in the form of
+ // { firstStage, lastStage, firstCycle, lastCycle } // index
+ if (Intinerary.FirstStage == 0) {
+ OS << " { 1, 0, 0, 0, 0 }";
+ } else {
+ OS << " { " <<
+ Intinerary.NumMicroOps << ", " <<
+ Intinerary.FirstStage << ", " <<
+ Intinerary.LastStage << ", " <<
+ Intinerary.FirstOperandCycle << ", " <<
+ Intinerary.LastOperandCycle << " }";
+ }
+ OS << ", // " << j << " " << ItinClassList[j]->getName() << "\n";
+ }
+ // End processor itinerary table
+ OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n";
+ OS << "};\n";
}
-
- // End processor itinerary table
- OS << " { 1, ~0U, ~0U, ~0U, ~0U } // end marker\n";
- OS << "};\n";
-
OS << '\n';
OS << "static const llvm::InstrItinerarySubtargetValue "
<< Name << " = {\n";
OS << " &" << Name << "Props,\n";
- OS << " " << Name << "Entries\n";
+ if (ItinList.empty())
+ OS << " 0\n";
+ else
+ OS << " " << Name << "Entries\n";
OS << "};\n";
}
}
diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index afb25be7ff..0ab21c8a54 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/utils/TableGen/X86RecognizableInstr.cpp
@@ -1106,6 +1106,8 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("VR128", TYPE_XMM128)
TYPE("f128mem", TYPE_M128)
TYPE("f256mem", TYPE_M256)
+ TYPE("v128mem", TYPE_M128)
+ TYPE("v256mem", TYPE_M256)
TYPE("FR64", TYPE_XMM64)
TYPE("f64mem", TYPE_M64FP)
TYPE("sdmem", TYPE_M64FP)
@@ -1235,6 +1237,8 @@ OperandEncoding RecognizableInstr::memoryEncodingFromString
ENCODING("sdmem", ENCODING_RM)
ENCODING("f128mem", ENCODING_RM)
ENCODING("f256mem", ENCODING_RM)
+ ENCODING("v128mem", ENCODING_RM)
+ ENCODING("v256mem", ENCODING_RM)
ENCODING("f64mem", ENCODING_RM)
ENCODING("f32mem", ENCODING_RM)
ENCODING("i128mem", ENCODING_RM)