[llvm] r322166 - [TableGen][AsmMatcherEmitter] Generate assembler checks for tied operands
Sander de Smalen via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 10 02:10:56 PST 2018
Author: s.desmalen
Date: Wed Jan 10 02:10:56 2018
New Revision: 322166
URL: http://llvm.org/viewvc/llvm-project?rev=322166&view=rev
Log:
[TableGen][AsmMatcherEmitter] Generate assembler checks for tied operands
Summary:
This extends TableGen's AsmMatcherEmitter with code that generates
a table with tied-operand constraints. The constraints are checked
when parsing the instruction. If an operand is not equal to its tied operand,
the assembler will give an error.
Patch [2/3] in a series to add operand constraint checks for SVE's predicated ADD/SUB.
Reviewers: olista01, rengolin, mcrosier, fhahn, craig.topper, evandro, echristo
Reviewed By: fhahn
Subscribers: javed.absar, llvm-commits
Differential Revision: https://reviews.llvm.org/D41446
Modified:
llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h
llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
Modified: llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h?rev=322166&r1=322165&r2=322166&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h (original)
+++ llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h Wed Jan 10 02:10:56 2018
@@ -271,6 +271,7 @@ class MCTargetAsmParser : public MCAsmPa
public:
enum MatchResultTy {
Match_InvalidOperand,
+ Match_InvalidTiedOperand,
Match_MissingFeature,
Match_MnemonicFail,
Match_Success,
Modified: llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp?rev=322166&r1=322165&r2=322166&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp Wed Jan 10 02:10:56 2018
@@ -3544,6 +3544,8 @@ static std::string AArch64MnemonicSpellC
bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
OperandVector &Operands) {
switch (ErrCode) {
+ case Match_InvalidTiedOperand:
+ return Error(Loc, "operand must match destination register");
case Match_MissingFeature:
return Error(Loc,
"instruction requires a CPU feature not currently enabled");
@@ -4063,6 +4065,7 @@ bool AArch64AsmParser::MatchAndEmitInstr
return showMatchError(ErrorLoc, MatchResult, Operands);
}
+ case Match_InvalidTiedOperand:
case Match_InvalidMemoryIndexed1:
case Match_InvalidMemoryIndexed2:
case Match_InvalidMemoryIndexed4:
Modified: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp?rev=322166&r1=322165&r2=322166&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp Wed Jan 10 02:10:56 2018
@@ -503,6 +503,20 @@ struct MatchableInfo {
/// removed.
SmallVector<AsmOperand, 8> AsmOperands;
+ /// AsmOperandEqualityConstraints - an array of pairs holding operand
+ /// constraints.
+ /// Each constraint is represented as a pair holding position of the token of
+ /// the operand asm name.
+ /// For example, an "AsmString" "add $Vd.s, $Vn.s, $Xn" would be
+ /// split in the following list of tokens:
+ ///
+ /// ['add', '$Vd', '.s', '$Vn', '.s', '$Xn']
+ ///
+ /// A constraint "$Vd = $Vn" (e.g. for a destructive operation) is rendered
+ /// as the pair {1,3} into this set (note that tokens are numbered starting
+ /// from 0).
+ SmallVector<std::pair<unsigned,unsigned>, 1> AsmOperandTiedConstraints;
+
/// Predicates - The required subtarget features to match this instruction.
SmallVector<const SubtargetFeatureInfo *, 4> RequiredFeatures;
@@ -885,6 +899,22 @@ extractSingletonRegisterForAsmOperand(Ma
// be some random non-register token, just ignore it.
}
+static Optional<size_t>
+getAsmOperandIdx(const SmallVectorImpl<MatchableInfo::AsmOperand> &AsmOperands,
+ std::string Name) {
+ const auto SymbolicName = std::string("$") + Name;
+ const auto Pos =
+ std::find_if(AsmOperands.begin(), AsmOperands.end(),
+ [&SymbolicName](const MatchableInfo::AsmOperand &A) {
+ return A.Token == SymbolicName;
+ });
+
+ if (Pos == AsmOperands.end())
+ return Optional<size_t>();
+
+ return Optional<size_t>(std::distance(AsmOperands.begin(), Pos));
+}
+
void MatchableInfo::initialize(const AsmMatcherInfo &Info,
SmallPtrSetImpl<Record*> &SingletonRegisters,
AsmVariantInfo const &Variant,
@@ -933,6 +963,37 @@ void MatchableInfo::initialize(const Asm
HasDeprecation =
DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false;
+
+ // Do not generate tied operand info if the instruction does not
+ // use the default AsmMatchConverter.
+ if (TheDef->getValue("AsmMatchConverter") &&
+ !TheDef->getValueAsString("AsmMatchConverter").empty())
+ return;
+
+ // Generate tied operand contraints info.
+ const auto &CGIOperands = getResultInst()->Operands;
+ for (const auto &CGIOp : CGIOperands) {
+ int TiedReg = CGIOp.getTiedRegister();
+ if (TiedReg == -1)
+ continue;
+
+ Optional<size_t> LHSIdx = getAsmOperandIdx(AsmOperands, CGIOp.Name);
+ Optional<size_t> RHSIdx =
+ getAsmOperandIdx(AsmOperands, CGIOperands[TiedReg].Name);
+ // Skipping operands with constraint but no reference in the
+ // AsmString. No need to throw a warning, as it's normal to have
+ // a $dst operand in the outs dag that is constrained to a $src
+ // operand in the ins dag but that does not appear in the AsmString.
+ if (!LHSIdx || !RHSIdx)
+ continue;
+
+ // Add the constraint. Using min/max as we consider constraint
+ // pair {A,B} and {B,A} the same
+ size_t AddMnemonicIdx = HasMnemonicFirst;
+ AsmOperandTiedConstraints.emplace_back(
+ std::min(*LHSIdx, *RHSIdx) + AddMnemonicIdx,
+ std::max(*LHSIdx, *RHSIdx) + AddMnemonicIdx);
+ }
}
/// Append an AsmOperand for the given substring of AsmString.
@@ -2831,6 +2892,80 @@ static void emitCustomOperandParsing(raw
OS << "}\n\n";
}
+static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ std::string Buf;
+ raw_string_ostream TmpOS(Buf);
+ TmpOS << "namespace {\n";
+ TmpOS << " struct TiedAsmOpndPair {\n";
+ TmpOS << " unsigned Opcode;\n";
+ TmpOS << " unsigned Opnd1;\n";
+ TmpOS << " unsigned Opnd2;\n";
+ TmpOS << " TiedAsmOpndPair(unsigned Opcode, unsigned Opnd1, unsigned "
+ "Opnd2)\n";
+ TmpOS << " : Opcode(Opcode), Opnd1(Opnd1), Opnd2(Opnd2) {}\n";
+ TmpOS << " };\n";
+ TmpOS << "} // end anonymous namespace\n\n";
+ TmpOS << "static const TiedAsmOpndPair TiedAsmOperandsTable[] = {\n";
+ bool TableEmpty = true;
+ for (const auto &Inst : Target.getInstructionsByEnumValue()) {
+ auto It = std::find_if(Info.Matchables.begin(), Info.Matchables.end(),
+ [&Inst](const std::unique_ptr<MatchableInfo> &MI) {
+ return (MI->TheDef->getID() == Inst->TheDef->getID());
+ });
+
+ if (It == Info.Matchables.end())
+ continue;
+
+ auto &Constraints = (**It).AsmOperandTiedConstraints;
+ if (Constraints.empty())
+ continue;
+
+ std::string Namespace = Inst->TheDef->getValueAsString("Namespace");
+
+ for (const auto &C : Constraints) {
+ TableEmpty = false;
+ TmpOS << " {";
+ TmpOS << Namespace << "::"<< (**It).TheDef->getName() << ", ";
+ TmpOS << C.first << ", " << C.second;
+ TmpOS << "},\n";
+ }
+ }
+ TmpOS << "};\n\n";
+ if (!TableEmpty)
+ OS << TmpOS.str();
+
+ OS << "static bool ";
+ OS << "checkAsmTiedOperandConstraints(const MCInst &Inst,\n";
+ OS << " const OperandVector &Operands,\n";
+ OS << " SMLoc &Loc) {\n";
+
+ if (TableEmpty) {
+ OS << "return true;\n}\n\n";
+ return;
+ }
+
+ OS << " const TiedAsmOpndPair SearchValue(Inst.getOpcode(), 0, 0);\n";
+ OS << " const auto Range = std::equal_range(\n";
+ OS << " std::begin(TiedAsmOperandsTable), std::end(TiedAsmOperandsTable),\n";
+ OS << " SearchValue, [](const TiedAsmOpndPair &a,\n";
+ OS << " const TiedAsmOpndPair &b) {\n";
+ OS << " return (a.Opcode < b.Opcode);\n";
+ OS << " });\n\n";
+ OS << " for (auto Item = Range.first; Item != Range.second; ++Item) {\n";
+ OS << " MCParsedAsmOperand &Op1 = *Operands[Item->Opnd1];\n";
+ OS << " MCParsedAsmOperand &Op2 = *Operands[Item->Opnd2];\n";
+ OS << " if ((Op1.isReg() && Op2.isReg()) &&\n";
+ OS << " (Op1.getReg() != Op2.getReg())) {\n";
+ OS << " Loc = Op2.getStartLoc();\n";
+ OS << " return false;\n";
+ OS << " }\n";
+ OS << " }\n";
+ OS << " return true;\n";
+ OS << "}\n\n";
+}
+
static void emitMnemonicSpellChecker(raw_ostream &OS, CodeGenTarget &Target,
unsigned VariantCount) {
OS << "static std::string " << Target.getName()
@@ -3078,6 +3213,9 @@ void AsmMatcherEmitter::run(raw_ostream
Info.Target.getName(), ClassName, "ComputeAvailableFeatures",
Info.SubtargetFeatures, OS);
+ if (!ReportMultipleNearMisses)
+ emitAsmTiedOperandConstraints(Target, Info, OS);
+
StringToOffsetTable StringTable;
size_t MaxNumOperands = 0;
@@ -3501,6 +3639,14 @@ void AsmMatcherEmitter::run(raw_ostream
OS << " if (matchingInlineAsm) {\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
+ if (!ReportMultipleNearMisses) {
+ OS << " SMLoc Loc;\n";
+ OS << " if (!checkAsmTiedOperandConstraints(Inst, Operands, Loc)) {\n";
+ OS << " ErrorInfo = " << (HasMnemonicFirst ? "1" : "SIndex") << ";\n";
+ OS << " return Match_InvalidTiedOperand;\n";
+ OS << " }\n";
+ OS << "\n";
+ }
OS << " return Match_Success;\n";
OS << " }\n\n";
OS << " // We have selected a definite instruction, convert the parsed\n"
@@ -3575,6 +3721,15 @@ void AsmMatcherEmitter::run(raw_ostream
OS << " }\n";
}
+ if (!ReportMultipleNearMisses) {
+ OS << " SMLoc Loc;\n";
+ OS << " if (!checkAsmTiedOperandConstraints(Inst, Operands, Loc)) {\n";
+ OS << " ErrorInfo = " << (HasMnemonicFirst ? "1" : "SIndex") << ";\n";
+ OS << " return Match_InvalidTiedOperand;\n";
+ OS << " }\n";
+ OS << "\n";
+ }
+
OS << " DEBUG_WITH_TYPE(\n";
OS << " \"asm-matcher\",\n";
OS << " dbgs() << \"Opcode result: complete match, selecting this opcode\\n\");\n";
More information about the llvm-commits
mailing list