Index: llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h =================================================================== --- llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h +++ llvm/trunk/include/llvm/MC/MCParser/MCTargetAsmParser.h @@ -14,6 +14,7 @@ #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" #include "llvm/Support/SMLoc.h" @@ -453,6 +454,15 @@ virtual void convertToMapAndConstraints(unsigned Kind, const OperandVector &Operands) = 0; + /// Returns whether two registers are equal and is used by the tied-operands + /// checks in the AsmMatcher. This method can be overridden allow e.g. a + /// sub- or super-register as the tied operand. + virtual bool regsEqual(const MCParsedAsmOperand &Op1, + const MCParsedAsmOperand &Op2) const { + assert(Op1.isReg() && Op2.isReg() && "Operands not all regs"); + return Op1.getReg() == Op2.getReg(); + } + // Return whether this parser uses assignment statements with equals tokens virtual bool equalIsAsmAssignment() { return true; }; // Return whether this start of statement identifier is a label Index: llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp =================================================================== --- llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp +++ llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp @@ -1855,8 +1855,22 @@ SrcOp2 = (SrcOp2 == (unsigned)-1) ? SrcOp1 : SrcOp2; } - ResOperands.push_back(ResOperand::getTiedOp(TiedOp, SrcOp1, SrcOp2)); - continue; + // If the alias operand is of a different operand class, we only want + // to benefit from the tied-operands check and just match the operand + // as a normal, but not copy the original (TiedOp) to the result + // instruction. We do this by passing -1 as the tied operand to copy. + if (ResultInst->Operands[i].Rec->getName() != + ResultInst->Operands[TiedOp].Rec->getName()) { + SrcOp1 = ResOperands[TiedOp].AsmOperandNum; + int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second; + StringRef Name = CGA.ResultOperands[AliasOpNo].getName(); + SrcOp2 = findAsmOperand(Name, SubIdx); + ResOperands.push_back( + ResOperand::getTiedOp((unsigned)-1, SrcOp1, SrcOp2)); + } else { + ResOperands.push_back(ResOperand::getTiedOp(TiedOp, SrcOp1, SrcOp2)); + continue; + } } // Handle all the suboperands for this operand. @@ -1986,7 +2000,8 @@ CvtOS << " std::begin(TiedAsmOperandTable)) &&\n"; CvtOS << " \"Tied operand not found\");\n"; CvtOS << " unsigned TiedResOpnd = TiedAsmOperandTable[OpIdx][0];\n"; - CvtOS << " Inst.addOperand(Inst.getOperand(TiedResOpnd));\n"; + CvtOS << " if (TiedResOpnd != (uint8_t) -1)\n"; + CvtOS << " Inst.addOperand(Inst.getOperand(TiedResOpnd));\n"; CvtOS << " break;\n"; CvtOS << " }\n"; @@ -2020,7 +2035,7 @@ enum { CVT_Done, CVT_Reg, CVT_Tied }; // Map of e.g. <0, 2, 3> -> "Tie_0_2_3" enum label. - std::map, std::string> + std::map, std::string> TiedOperandsEnumMap; for (auto &II : Infos) { @@ -2143,10 +2158,13 @@ // If this operand is tied to a previous one, just copy the MCInst // operand from the earlier one.We can only tie single MCOperand values. assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand"); - unsigned TiedOp = OpInfo.TiedOperands.ResOpnd; - unsigned SrcOp1 = OpInfo.TiedOperands.SrcOpnd1Idx + HasMnemonicFirst; - unsigned SrcOp2 = OpInfo.TiedOperands.SrcOpnd2Idx + HasMnemonicFirst; - assert(i > TiedOp && "Tied operand precedes its target!"); + uint8_t TiedOp = OpInfo.TiedOperands.ResOpnd; + uint8_t SrcOp1 = + OpInfo.TiedOperands.SrcOpnd1Idx + HasMnemonicFirst; + uint8_t SrcOp2 = + OpInfo.TiedOperands.SrcOpnd2Idx + HasMnemonicFirst; + assert((i > TiedOp || TiedOp == (uint8_t)-1) && + "Tied operand precedes its target!"); auto TiedTupleName = std::string("Tie") + utostr(TiedOp) + '_' + utostr(SrcOp1) + '_' + utostr(SrcOp2); Signature += "__" + TiedTupleName; @@ -2246,9 +2264,10 @@ if (TiedOperandsEnumMap.size()) { // The number of tied operand combinations will be small in practice, // but just add the assert to be sure. - assert(TiedOperandsEnumMap.size() <= 255 && + assert(TiedOperandsEnumMap.size() <= 254 && "Too many tied-operand combinations to reference with " - "an 8bit offset from the conversion table"); + "an 8bit offset from the conversion table, where index " + "'255' is reserved as operand not to be copied."); OS << "enum {\n"; for (auto &KV : TiedOperandsEnumMap) { @@ -2256,15 +2275,17 @@ } OS << "};\n\n"; - OS << "const char TiedAsmOperandTable[][3] = {\n"; + OS << "const uint8_t TiedAsmOperandTable[][3] = {\n"; for (auto &KV : TiedOperandsEnumMap) { - OS << " /* " << KV.second << " */ { " << std::get<0>(KV.first) << ", " - << std::get<1>(KV.first) << ", " << std::get<2>(KV.first) << " },\n"; + OS << " /* " << KV.second << " */ { " + << utostr(std::get<0>(KV.first)) << ", " + << utostr(std::get<1>(KV.first)) << ", " + << utostr(std::get<2>(KV.first)) << " },\n"; } OS << "};\n\n"; } else - OS << "const char TiedAsmOperandTable[][3] = { /* empty */ {0, 0, 0} " - "};\n\n"; + OS << "const uint8_t TiedAsmOperandTable[][3] = " + "{ /* empty */ {0, 0, 0} };\n\n"; OS << "namespace {\n"; @@ -2303,9 +2324,9 @@ // For a tied operand, emit a reference to the TiedAsmOperandTable // that contains the operand to copy, and the parsed operands to // check for their tied constraints. - auto Key = std::make_tuple((unsigned)ConversionTable[Row][i + 1], - (unsigned)ConversionTable[Row][i + 2], - (unsigned)ConversionTable[Row][i + 3]); + auto Key = std::make_tuple((uint8_t)ConversionTable[Row][i + 1], + (uint8_t)ConversionTable[Row][i + 2], + (uint8_t)ConversionTable[Row][i + 3]); auto TiedOpndEnum = TiedOperandsEnumMap.find(Key); assert(TiedOpndEnum != TiedOperandsEnumMap.end() && "No record for tied operand pair"); @@ -2978,8 +2999,12 @@ static void emitAsmTiedOperandConstraints(CodeGenTarget &Target, AsmMatcherInfo &Info, raw_ostream &OS) { + std::string AsmParserName = + Info.AsmParser->getValueAsString("AsmParserClassName"); OS << "static bool "; - OS << "checkAsmTiedOperandConstraints(unsigned Kind,\n"; + OS << "checkAsmTiedOperandConstraints(const " << Target.getName() + << AsmParserName << "&AsmParser,\n"; + OS << " unsigned Kind,\n"; OS << " const OperandVector &Operands,\n"; OS << " uint64_t &ErrorInfo) {\n"; OS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"; @@ -2996,10 +3021,11 @@ OS << " if (OpndNum1 != OpndNum2) {\n"; OS << " auto &SrcOp1 = Operands[OpndNum1];\n"; OS << " auto &SrcOp2 = Operands[OpndNum2];\n"; - OS << " if (SrcOp1->isReg() && SrcOp2->isReg() &&\n"; - OS << " SrcOp1->getReg() != SrcOp2->getReg()) {\n"; - OS << " ErrorInfo = OpndNum2;\n"; - OS << " return false;\n"; + OS << " if (SrcOp1->isReg() && SrcOp2->isReg()) {\n"; + OS << " if (!AsmParser.regsEqual(*SrcOp1, *SrcOp2)) {\n"; + OS << " ErrorInfo = OpndNum2;\n"; + OS << " return false;\n"; + OS << " }\n"; OS << " }\n"; OS << " }\n"; OS << " break;\n"; @@ -3686,7 +3712,8 @@ OS << " if (matchingInlineAsm) {\n"; OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; if (!ReportMultipleNearMisses) { - OS << " if (!checkAsmTiedOperandConstraints(it->ConvertFn, Operands, ErrorInfo))\n"; + OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, " + "Operands, ErrorInfo))\n"; OS << " return Match_InvalidTiedOperand;\n"; OS << "\n"; } @@ -3765,7 +3792,8 @@ } if (!ReportMultipleNearMisses) { - OS << " if (!checkAsmTiedOperandConstraints(it->ConvertFn, Operands, ErrorInfo))\n"; + OS << " if (!checkAsmTiedOperandConstraints(*this, it->ConvertFn, " + "Operands, ErrorInfo))\n"; OS << " return Match_InvalidTiedOperand;\n"; OS << "\n"; } Index: llvm/trunk/utils/TableGen/CodeGenInstruction.cpp =================================================================== --- llvm/trunk/utils/TableGen/CodeGenInstruction.cpp +++ llvm/trunk/utils/TableGen/CodeGenInstruction.cpp @@ -630,8 +630,14 @@ // of a complex operand, in which case we include them anyways, as we // don't have any other way to specify the whole operand. if (ResultInst->Operands[i].MINumOperands == 1 && - ResultInst->Operands[i].getTiedRegister() != -1) - continue; + ResultInst->Operands[i].getTiedRegister() != -1) { + // Tied operands of different RegisterClass should be explicit within an + // instruction's syntax and so cannot be skipped. + int TiedOpNum = ResultInst->Operands[i].getTiedRegister(); + if (ResultInst->Operands[i].Rec->getName() == + ResultInst->Operands[TiedOpNum].Rec->getName()) + continue; + } if (AliasOpNo >= Result->getNumArgs()) PrintFatalError(R->getLoc(), "not enough arguments for instruction!");