summaryrefslogtreecommitdiffstats
path: root/llvm/utils
diff options
context:
space:
mode:
authorNikolay Haustov <Nikolay.Haustov@amd.com>2016-03-01 08:34:43 +0000
committerNikolay Haustov <Nikolay.Haustov@amd.com>2016-03-01 08:34:43 +0000
commitea8febde04be761d44e03318a6b4e8d51f31408e (patch)
treef349bbe6354f88847390d4dd25b3a05311981650 /llvm/utils
parent95b4fcd37748785dc2ce8d06b1f728320d60eb69 (diff)
downloadbcm5719-llvm-ea8febde04be761d44e03318a6b4e8d51f31408e.tar.gz
bcm5719-llvm-ea8febde04be761d44e03318a6b4e8d51f31408e.zip
[TableGen] AsmMatcher: Skip optional operands in the midle of instruction if it is not present
Previosy, if actual instruction have one of optional operands then other optional operands listed before this also should be presented. For example instruction v_fract_f32 v0, v1, mul:2 have one optional operand - OMod and do not have optional operand clamp. Previously this was not allowed because clamp is listed before omod in AsmString: string AsmString = "v_fract_f32$vdst, $src0_modifiers$clamp$omod"; Making this work required some hacks (both OMod and Clamp match classes have same PredicateMethod). Now, if MatchInstructionImpl meets formal optional operand that is not presented in actual instruction it skips this formal operand and tries to match current actual operand with next formal. Patch by: Sam Kolton Review: http://reviews.llvm.org/D17568 [AMDGPU] Assembler: Check immediate types for several optional operands in predicate methods With this change you should place optional operands in order specified by asm string: clamp -> omod offset -> glc -> slc -> tfe Fixes for several tests. Depends on D17568 Patch by: Sam Kolton Review: http://reviews.llvm.org/D17644 llvm-svn: 262314
Diffstat (limited to 'llvm/utils')
-rw-r--r--llvm/utils/TableGen/AsmMatcherEmitter.cpp35
1 files changed, 21 insertions, 14 deletions
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 103ed99e35c..799f20d0b94 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -3108,37 +3108,44 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Emit check that the subclasses match.
OS << " bool OperandsValid = true;\n";
- OS << " for (unsigned i = " << (HasMnemonicFirst ? "0" : "SIndex")
- << "; i != " << MaxNumOperands << "; ++i) {\n";
- OS << " auto Formal = static_cast<MatchClassKind>(it->Classes[i]);\n";
- OS << " if (i" << (HasMnemonicFirst ? "+1" : "")
- << " >= Operands.size()) {\n";
+ OS << " for (unsigned FormalIdx = " << (HasMnemonicFirst ? "0" : "SIndex")
+ << ", ActualIdx = " << (HasMnemonicFirst ? "1" : "SIndex")
+ << "; FormalIdx != " << MaxNumOperands << "; ++FormalIdx) {\n";
+ OS << " auto Formal = "
+ << "static_cast<MatchClassKind>(it->Classes[FormalIdx]);\n";
+ OS << " if (ActualIdx >= Operands.size()) {\n";
OS << " OperandsValid = (Formal == " <<"InvalidMatchClass) || "
"isSubclass(Formal, OptionalMatchClass);\n";
- OS << " if (!OperandsValid) ErrorInfo = i"
- << (HasMnemonicFirst ? "+1" : "") << ";\n";
+ OS << " if (!OperandsValid) ErrorInfo = ActualIdx;\n";
OS << " break;\n";
OS << " }\n";
- OS << " MCParsedAsmOperand &Actual = *Operands[i"
- << (HasMnemonicFirst ? "+1" : "") << "];\n";
+ OS << " MCParsedAsmOperand &Actual = *Operands[ActualIdx];\n";
OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n";
- OS << " if (Diag == Match_Success)\n";
+ OS << " if (Diag == Match_Success) {\n";
+ OS << " ++ActualIdx;\n";
OS << " continue;\n";
+ OS << " }\n";
OS << " // If the generic handler indicates an invalid operand\n";
OS << " // failure, check for a special case.\n";
OS << " if (Diag == Match_InvalidOperand) {\n";
OS << " Diag = validateTargetOperandClass(Actual, Formal);\n";
- OS << " if (Diag == Match_Success)\n";
+ OS << " if (Diag == Match_Success) {\n";
+ OS << " ++ActualIdx;\n";
OS << " continue;\n";
+ OS << " }\n";
OS << " }\n";
+ OS << " // If current formal operand wasn't matched and it is optional\n"
+ << " // then try to match next formal operand\n";
+ OS << " if (Diag == Match_InvalidOperand "
+ << "&& isSubclass(Formal, OptionalMatchClass))\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 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"
- << (HasMnemonicFirst ? "+1" : "") << ")) {\n";
- OS << " ErrorInfo = i" << (HasMnemonicFirst ? "+1" : "") << ";\n";
+ OS << " (it == MnemonicRange.first || ErrorInfo <= ActualIdx)) {\n";
+ OS << " ErrorInfo = ActualIdx;\n";
OS << " // InvalidOperand is the default. Prefer specificity.\n";
OS << " if (Diag != Match_InvalidOperand)\n";
OS << " RetCode = Diag;\n";
OpenPOWER on IntegriCloud