[llvm] [MC] Teach checkAsmTiedOperandConstraints about optional operands (PR #81381)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Sat Feb 10 14:37:50 PST 2024
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/81381
>From 22bada0f96087f0e54dcfeadd4938f408af81949 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 11 Feb 2024 00:24:47 +0300
Subject: [PATCH 1/3] [MC] Teach checkAsmTiedOperandConstraints about optional
operands
At some point in the past, optional operands have become allowed in the
middle of an instruction. However, `checkAsmTiedOperandConstrains`
hasn't been modified to support this. This patch adds the support by
copying the necessary logic from `convertToMCInst`.
---
llvm/utils/TableGen/AsmMatcherEmitter.cpp | 68 +++++++++++++++++------
1 file changed, 51 insertions(+), 17 deletions(-)
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 9065885618069b..bd4a5dab171789 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -1958,7 +1958,7 @@ static unsigned
emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
bool HasMnemonicFirst, bool HasOptionalOperands,
- raw_ostream &OS) {
+ unsigned MaxNumOperands, raw_ostream &OS) {
SmallSetVector<CachedHashString, 16> OperandConversionKinds;
SmallSetVector<CachedHashString, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t>> ConversionTable;
@@ -1988,10 +1988,6 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
CvtOS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
CvtOS << " const uint8_t *Converter = ConversionTable[Kind];\n";
if (HasOptionalOperands) {
- size_t MaxNumOperands = 0;
- for (const auto &MI : Infos) {
- MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
- }
CvtOS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
<< "] = { 0 };\n";
CvtOS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
@@ -3028,18 +3024,33 @@ emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
}
static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
- AsmMatcherInfo &Info,
- raw_ostream &OS) {
+ AsmMatcherInfo &Info, raw_ostream &OS,
+ bool HasOptionalOperands,
+ unsigned MaxNumOperands) {
std::string AsmParserName =
std::string(Info.AsmParser->getValueAsString("AsmParserClassName"));
OS << "static bool ";
OS << "checkAsmTiedOperandConstraints(const " << Target.getName()
<< AsmParserName << "&AsmParser,\n";
- OS << " unsigned Kind,\n";
- OS << " const OperandVector &Operands,\n";
+ OS << " unsigned Kind, const OperandVector "
+ "&Operands,\n";
+ if (HasOptionalOperands)
+ OS << " const SmallBitVector "
+ "&OptionalOperandsMask,\n";
OS << " uint64_t &ErrorInfo) {\n";
OS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
OS << " const uint8_t *Converter = ConversionTable[Kind];\n";
+ if (HasOptionalOperands) {
+ OS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
+ << "] = { 0 };\n";
+ OS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
+ << ");\n";
+ OS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
+ << "; ++i) {\n";
+ OS << " DefaultsOffset[i + 1] = NumDefaults;\n";
+ OS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
+ OS << " }\n";
+ }
OS << " for (const uint8_t *p = Converter; *p; p += 2) {\n";
OS << " switch (*p) {\n";
OS << " case CVT_Tied: {\n";
@@ -3049,6 +3060,10 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
OS << " \"Tied operand not found\");\n";
OS << " unsigned OpndNum1 = TiedAsmOperandTable[OpIdx][1];\n";
OS << " unsigned OpndNum2 = TiedAsmOperandTable[OpIdx][2];\n";
+ if (HasOptionalOperands) {
+ OS << " OpndNum1 = OpndNum1 - DefaultsOffset[OpndNum1];\n";
+ OS << " OpndNum2 = OpndNum2 - DefaultsOffset[OpndNum2];\n";
+ }
OS << " if (OpndNum1 != OpndNum2) {\n";
OS << " auto &SrcOp1 = Operands[OpndNum1];\n";
OS << " auto &SrcOp2 = Operands[OpndNum2];\n";
@@ -3368,12 +3383,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Generate the function that remaps for mnemonic aliases.
bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target);
+ size_t MaxNumOperands = 0;
+ for (const auto &MI : Info.Matchables)
+ MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
+
// Generate the convertToMCInst function to convert operands into an MCInst.
// Also, generate the convertToMapAndConstraints function for MS-style inline
// assembly. The latter doesn't actually generate a MCInst.
unsigned NumConverters =
emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst,
- HasOptionalOperands, OS);
+ HasOptionalOperands, MaxNumOperands, OS);
// Emit the enumeration for classes which participate in matching.
emitMatchClassEnumeration(Target, Info.Classes, OS);
@@ -3402,15 +3421,14 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
Info.SubtargetFeatures, OS);
if (!ReportMultipleNearMisses)
- emitAsmTiedOperandConstraints(Target, Info, OS);
+ emitAsmTiedOperandConstraints(Target, Info, OS, HasOptionalOperands,
+ MaxNumOperands);
StringToOffsetTable StringTable;
- size_t MaxNumOperands = 0;
unsigned MaxMnemonicIndex = 0;
bool HasDeprecation = false;
for (const auto &MI : Info.Matchables) {
- MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
HasDeprecation |= MI->HasDeprecation;
// Store a pascal-style length byte in the mnemonic.
@@ -3928,8 +3946,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " if (matchingInlineAsm) {\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
if (!ReportMultipleNearMisses) {
- OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
- "Operands, ErrorInfo))\n";
+ if (HasOptionalOperands) {
+ OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
+ "Operands,\n";
+ OS << " OptionalOperandsMask, "
+ "ErrorInfo))\n";
+ } else {
+ OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
+ "Operands,\n";
+ OS << " ErrorInfo))\n";
+ }
OS << " return Match_InvalidTiedOperand;\n";
OS << "\n";
}
@@ -4019,8 +4045,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
}
if (!ReportMultipleNearMisses) {
- OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
- "Operands, ErrorInfo))\n";
+ if (HasOptionalOperands) {
+ OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
+ "Operands,\n";
+ OS << " OptionalOperandsMask, "
+ "ErrorInfo))\n";
+ } else {
+ OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
+ "Operands,\n";
+ OS << " ErrorInfo))\n";
+ }
OS << " return Match_InvalidTiedOperand;\n";
OS << "\n";
}
>From 800c974ad670bdcdc672f0d363818eb81f11cfff Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 11 Feb 2024 00:34:10 +0300
Subject: [PATCH 2/3] Apply clang-format suggestion.
---
llvm/utils/TableGen/AsmMatcherEmitter.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index bd4a5dab171789..c11c6d4d3ca651 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -3042,11 +3042,11 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
OS << " const uint8_t *Converter = ConversionTable[Kind];\n";
if (HasOptionalOperands) {
OS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
- << "] = { 0 };\n";
+ << "] = { 0 };\n";
OS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
- << ");\n";
+ << ");\n";
OS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
- << "; ++i) {\n";
+ << "; ++i) {\n";
OS << " DefaultsOffset[i + 1] = NumDefaults;\n";
OS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
OS << " }\n";
>From 0bd96c20575abb2610fee39d69d0d575462742cf Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Sun, 11 Feb 2024 01:37:35 +0300
Subject: [PATCH 3/3] Pull the duplicated logic to a common place
---
llvm/utils/TableGen/AsmMatcherEmitter.cpp | 65 +++++++++--------------
1 file changed, 26 insertions(+), 39 deletions(-)
diff --git a/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index c11c6d4d3ca651..2c6708ae0dc4fb 100644
--- a/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -1958,7 +1958,7 @@ static unsigned
emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
bool HasMnemonicFirst, bool HasOptionalOperands,
- unsigned MaxNumOperands, raw_ostream &OS) {
+ raw_ostream &OS) {
SmallSetVector<CachedHashString, 16> OperandConversionKinds;
SmallSetVector<CachedHashString, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t>> ConversionTable;
@@ -1978,7 +1978,8 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
<< "convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
<< " const OperandVector &Operands,\n"
- << " const SmallBitVector &OptionalOperandsMask) {\n";
+ << " const SmallBitVector &OptionalOperandsMask,\n"
+ << " ArrayRef<unsigned> DefaultsOffset) {\n";
} else {
CvtOS << "void " << Target.getName() << ClassName << "::\n"
<< "convertToMCInst(unsigned Kind, MCInst &Inst, "
@@ -1987,17 +1988,6 @@ emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
}
CvtOS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
CvtOS << " const uint8_t *Converter = ConversionTable[Kind];\n";
- if (HasOptionalOperands) {
- CvtOS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
- << "] = { 0 };\n";
- CvtOS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
- << ");\n";
- CvtOS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
- << "; ++i) {\n";
- CvtOS << " DefaultsOffset[i + 1] = NumDefaults;\n";
- CvtOS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
- CvtOS << " }\n";
- }
CvtOS << " unsigned OpIdx;\n";
CvtOS << " Inst.setOpcode(Opcode);\n";
CvtOS << " for (const uint8_t *p = Converter; *p; p += 2) {\n";
@@ -3025,8 +3015,7 @@ emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
AsmMatcherInfo &Info, raw_ostream &OS,
- bool HasOptionalOperands,
- unsigned MaxNumOperands) {
+ bool HasOptionalOperands) {
std::string AsmParserName =
std::string(Info.AsmParser->getValueAsString("AsmParserClassName"));
OS << "static bool ";
@@ -3035,22 +3024,10 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target,
OS << " unsigned Kind, const OperandVector "
"&Operands,\n";
if (HasOptionalOperands)
- OS << " const SmallBitVector "
- "&OptionalOperandsMask,\n";
+ OS << " ArrayRef<unsigned> DefaultsOffset,\n";
OS << " uint64_t &ErrorInfo) {\n";
OS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
OS << " const uint8_t *Converter = ConversionTable[Kind];\n";
- if (HasOptionalOperands) {
- OS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
- << "] = { 0 };\n";
- OS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
- << ");\n";
- OS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
- << "; ++i) {\n";
- OS << " DefaultsOffset[i + 1] = NumDefaults;\n";
- OS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
- OS << " }\n";
- }
OS << " for (const uint8_t *p = Converter; *p; p += 2) {\n";
OS << " switch (*p) {\n";
OS << " case CVT_Tied: {\n";
@@ -3303,7 +3280,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< "unsigned Opcode,\n"
<< " const OperandVector &Operands,\n"
<< " const SmallBitVector "
- "&OptionalOperandsMask);\n";
+ "&OptionalOperandsMask,\n"
+ << " ArrayRef<unsigned> DefaultsOffset);\n";
} else {
OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
<< "unsigned Opcode,\n"
@@ -3383,16 +3361,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Generate the function that remaps for mnemonic aliases.
bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target);
- size_t MaxNumOperands = 0;
- for (const auto &MI : Info.Matchables)
- MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
-
// Generate the convertToMCInst function to convert operands into an MCInst.
// Also, generate the convertToMapAndConstraints function for MS-style inline
// assembly. The latter doesn't actually generate a MCInst.
unsigned NumConverters =
emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst,
- HasOptionalOperands, MaxNumOperands, OS);
+ HasOptionalOperands, OS);
// Emit the enumeration for classes which participate in matching.
emitMatchClassEnumeration(Target, Info.Classes, OS);
@@ -3421,14 +3395,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
Info.SubtargetFeatures, OS);
if (!ReportMultipleNearMisses)
- emitAsmTiedOperandConstraints(Target, Info, OS, HasOptionalOperands,
- MaxNumOperands);
+ emitAsmTiedOperandConstraints(Target, Info, OS, HasOptionalOperands);
StringToOffsetTable StringTable;
+ size_t MaxNumOperands = 0;
unsigned MaxMnemonicIndex = 0;
bool HasDeprecation = false;
for (const auto &MI : Info.Matchables) {
+ MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
HasDeprecation |= MI->HasDeprecation;
// Store a pascal-style length byte in the mnemonic.
@@ -3943,13 +3918,25 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
}
+ if (HasOptionalOperands) {
+ OS << " unsigned DefaultsOffset[" << (MaxNumOperands + 1)
+ << "] = { 0 };\n";
+ OS << " assert(OptionalOperandsMask.size() == " << (MaxNumOperands)
+ << ");\n";
+ OS << " for (unsigned i = 0, NumDefaults = 0; i < " << (MaxNumOperands)
+ << "; ++i) {\n";
+ OS << " DefaultsOffset[i + 1] = NumDefaults;\n";
+ OS << " NumDefaults += (OptionalOperandsMask[i] ? 1 : 0);\n";
+ OS << " }\n\n";
+ }
+
OS << " if (matchingInlineAsm) {\n";
OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
if (!ReportMultipleNearMisses) {
if (HasOptionalOperands) {
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
"Operands,\n";
- OS << " OptionalOperandsMask, "
+ OS << " DefaultsOffset, "
"ErrorInfo))\n";
} else {
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
@@ -3965,7 +3952,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
<< " // operands into the appropriate MCInst.\n";
if (HasOptionalOperands) {
OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands,\n"
- << " OptionalOperandsMask);\n";
+ << " OptionalOperandsMask, DefaultsOffset);\n";
} else {
OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";
}
@@ -4048,7 +4035,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (HasOptionalOperands) {
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
"Operands,\n";
- OS << " OptionalOperandsMask, "
+ OS << " DefaultsOffset, "
"ErrorInfo))\n";
} else {
OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, "
More information about the llvm-commits
mailing list