Index: include/llvm/Target/Target.td =================================================================== --- include/llvm/Target/Target.td +++ include/llvm/Target/Target.td @@ -605,6 +605,10 @@ // match failure error message. By default, use a generic "invalid operand" // diagnostic. The target AsmParser maps these codes to text. string DiagnosticType = ""; + + /// Set to 1 if this operand is optional and not always required. Optional + /// operands must be at the end of the operand list. + bit IsOptional = 0; } def ImmAsmOperand : AsmOperandClass { Index: utils/TableGen/AsmMatcherEmitter.cpp =================================================================== --- utils/TableGen/AsmMatcherEmitter.cpp +++ utils/TableGen/AsmMatcherEmitter.cpp @@ -199,6 +199,10 @@ /// For custom match classes: the diagnostic kind for when the predicate fails. std::string DiagnosticType; + + /// Is this operand optional and not always required. + bool IsOptional; + public: /// isRegisterClass() - Check if this is a register class. bool isRegisterClass() const { @@ -1058,6 +1062,7 @@ Entry->RenderMethod = ""; Entry->ParserMethod = ""; Entry->DiagnosticType = ""; + Entry->IsOptional = false; } return Entry; @@ -1193,6 +1198,7 @@ CI->Registers = RS; // FIXME: diagnostic type. CI->DiagnosticType = ""; + CI->IsOptional = false; RegisterSetClasses.insert(std::make_pair(RS, CI)); ++Index; } @@ -1307,6 +1313,10 @@ if (StringInit *SI = dyn_cast(DiagnosticType)) CI->DiagnosticType = SI->getValue(); + Init *IsOptional = Rec->getValueInit("IsOptional"); + if (BitInit *BI = dyn_cast(IsOptional)) + CI->IsOptional = BI->getValue(); + ++Index; } } @@ -2041,6 +2051,7 @@ << "/// instruction matching.\n"; OS << "enum MatchClassKind {\n"; OS << " InvalidMatchClass = 0,\n"; + OS << " OptionalMatchClass = 1,\n"; for (const auto &CI : Infos) { OS << " " << CI.Name << ", // "; if (CI.Kind == ClassInfo::Token) { @@ -2132,6 +2143,8 @@ SS << " return false;\n"; for (const auto &A : Infos) { std::vector SuperClasses; + if (A.IsOptional) + SuperClasses.push_back("OptionalMatchClass"); for (const auto &B : Infos) { if (&A != &B && A.isSubsetOf(B)) SuperClasses.push_back(B.Name); @@ -2976,7 +2989,8 @@ OS << " for (unsigned i = SIndex; i != " << MaxNumOperands << "; ++i) {\n"; OS << " auto Formal = static_cast(it->Classes[i]);\n"; OS << " if (i >= Operands.size()) {\n"; - OS << " OperandsValid = (Formal == " <<"InvalidMatchClass);\n"; + OS << " OperandsValid = (Formal == " <<"InvalidMatchClass) || " << + "isSubclass(Formal, OptionalMatchClass);\n"; OS << " if (!OperandsValid) ErrorInfo = i;\n"; OS << " break;\n"; OS << " }\n";